django在QuerySet中给定当前对象获取下一个对象

发布于 2025-02-08 13:39:54 字数 598 浏览 3 评论 0原文

我有一个章节模型,因此在章节详细信息视图中,我希望用户能够导航到下一章和上章,因为他正在查看当前章节,所以这是在Django中最有效的方法,

这是我的章节模型

class Chapter(models.Model):

    title         = models.CharField(max_length=100)
    slug          = models.SlugField(blank=True,null=True,)
    module       = models.ForeignKey(Module,on_delete=models.CASCADE,null=True,blank=True,)
    content       = models.TextField()
    
    def __str__(self):
         return self.title
    

   

i have seen some answers while they use the python list method to turn the queryset in to an array but i think maybe there is a better way 

I have a chapter model so in the chapter detail view i want the user to be able to navigate to the next and to previous chapter given the current chapter that he's viewing so what's is the most efficient way to that in django

this is my chapter model

class Chapter(models.Model):

    title         = models.CharField(max_length=100)
    slug          = models.SlugField(blank=True,null=True,)
    module       = models.ForeignKey(Module,on_delete=models.CASCADE,null=True,blank=True,)
    content       = models.TextField()
    
    def __str__(self):
         return self.title
    

   

i have seen some answers while they use the python list method to turn the queryset in to an array but i think maybe there is a better way 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

独﹏钓一江月 2025-02-15 13:39:54

我要谨慎使用ID作为位置标识符,因为只有连续创建章节时才可靠 - 您不能创建一个章节模块,然后在第一个模块上添加最后一章,您可以't重新排列章节。我将模型扩展到包含订单字段,

在模型中

ordering = models.PositiveSmallIntegerField()

class Meta:
    constraints = [
        models.UniqueConstraint(
            fields=["module", "ordering"], name="unique_order_in_modules"
        )
    ]

唯一的模块,然后您 定义get_next_chapter方法(get get上一章都可以使用类似)

class Chapter(models.Model):
... fields
    def get_next_chapter_url(self):
        next_chapter_index = self.ordering + 1
        next_chapter = Chapter.objects.filter(module = self.module, ordering = next_chapter_index).first()

,但是...虽然这将起作用,但每个引用它是另一个数据库调用。为了提高效率,您可以在视图中使用订单号来在单个查询中获取所有相关章节,例如

views.py

def view_chapter(request, module_id, chap_num):
    #define vars
    chapters = [chap_num - 1, chap_num, chap_num + 1]
    prev_chapter = None
    chapter = None
    next_chapter = None

    #perform single query
    queryset = Chapters.objects.filter(ordering__in=chapters, module_id=module_id).select_related('module') 
    #I've thrown selected_related in so you can use things like chapter.module.name in your template without additional database calls.
    
    #define context vars
    for chapter in queryset:
       if chapter.ordering == chap_num:
           chapter=chapter
       elif chapter.ordering == chap_num - 1:
           prev_chapter = chapter
       elif chapter.ordering == chap_num + 1:
           next_chapter = chapter

    context = {"chapter": chapter, "prev-chapter": prev_chapter, "next_chapter": next_chapter}
        

,然后在模板中获取所有相关章节

<a href="{% url 'view chapter' chapter.module_id prev_chapter.ordering %}"> previous chapter</a>

I'd be careful about using id as a positional identifier, as that is only dependable if chapters are created consecutively - you can't create one module of chapters, then another, then add a final chapter on the first module, and you can't rearrange chapters later. I'd extend the model to include a order field, unique for module

in your model

ordering = models.PositiveSmallIntegerField()

class Meta:
    constraints = [
        models.UniqueConstraint(
            fields=["module", "ordering"], name="unique_order_in_modules"
        )
    ]

Then you could define a get_next_chapter method (get previous chapter would work similarly)

class Chapter(models.Model):
... fields
    def get_next_chapter_url(self):
        next_chapter_index = self.ordering + 1
        next_chapter = Chapter.objects.filter(module = self.module, ordering = next_chapter_index).first()

But...while this will work, each reference to it is another database call. To be more efficient, you could utilise the ordering number in your view to get all the relevant chapters in a single query, eg:

views.py

def view_chapter(request, module_id, chap_num):
    #define vars
    chapters = [chap_num - 1, chap_num, chap_num + 1]
    prev_chapter = None
    chapter = None
    next_chapter = None

    #perform single query
    queryset = Chapters.objects.filter(ordering__in=chapters, module_id=module_id).select_related('module') 
    #I've thrown selected_related in so you can use things like chapter.module.name in your template without additional database calls.
    
    #define context vars
    for chapter in queryset:
       if chapter.ordering == chap_num:
           chapter=chapter
       elif chapter.ordering == chap_num - 1:
           prev_chapter = chapter
       elif chapter.ordering == chap_num + 1:
           next_chapter = chapter

    context = {"chapter": chapter, "prev-chapter": prev_chapter, "next_chapter": next_chapter}
        

and then in your template

<a href="{% url 'view chapter' chapter.module_id prev_chapter.ordering %}"> previous chapter</a>
飘过的浮云 2025-02-15 13:39:54

我考虑了分页,但我写了最快的方式。

class Chapter(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(blank=True,null=True,)
    module = models.ForeignKey(Module,on_delete=models.CASCADE,null=True,blank=True,)
    content = models.TextField()
    
    def __str__(self):
        return self.title

    def get_next(self):
        return Chapter.objects.filter(id__gt=self.id).order_by('id').first()
        

在HTML中,

您需要在章节循环中调用get_next。我认为您的章节URL为详细信息/&lt; id&gt;

  <a href= {% url 'detail' obj.get_next.id }}> next chapter </a>
    

I thought about pagination but I wrote the fastest way.

class Chapter(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(blank=True,null=True,)
    module = models.ForeignKey(Module,on_delete=models.CASCADE,null=True,blank=True,)
    content = models.TextField()
    
    def __str__(self):
        return self.title

    def get_next(self):
        return Chapter.objects.filter(id__gt=self.id).order_by('id').first()
        

in HTML

You need to call get_next in chapter objects loop. I suppose your chapter URL as detail/<id>

  <a href= {% url 'detail' obj.get_next.id }}> next chapter </a>
    
喜你已久 2025-02-15 13:39:54

您可以在细节视图的背景下提供它们。例如,例如以下方法,例如以下方法,例如

class ChapterDetailView(DetailView):
    model = Chapter
    template_name = 'chapter_detail.html'
    context_object_name = 'current_chapter'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['previous_chapter'] = your_previous_chapter_link_if_any_else_none
        context['next_chapter'] = your_next_chapter_link_if_any_else_none
        return context

以下方法,presurn_chapter和next_ chapter可能是在模型中定义URL.py如下

class Chapter(models.Model):
    # ... your models field
    def get_next_chapter_url(self):
        next_chapter = Chapter.objects.filter(id__gt=self.id).order_by('id').first()
        if next_chapter:
            return reverse('chapter-detail', kwargs={'id': next_chapter.id})

和章节详细信息页面模板,假设上下文对象名称为current_ chapter

<a href="{{current_chapter.get_next_chapter_url}}">Next Chapter</a>

You can provide them in a context of detail view. For example like previous_chapter, current_chapter and next_chapter as follow

class ChapterDetailView(DetailView):
    model = Chapter
    template_name = 'chapter_detail.html'
    context_object_name = 'current_chapter'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['previous_chapter'] = your_previous_chapter_link_if_any_else_none
        context['next_chapter'] = your_next_chapter_link_if_any_else_none
        return context

Another approach may be defining urls in models.py as follow

class Chapter(models.Model):
    # ... your models field
    def get_next_chapter_url(self):
        next_chapter = Chapter.objects.filter(id__gt=self.id).order_by('id').first()
        if next_chapter:
            return reverse('chapter-detail', kwargs={'id': next_chapter.id})

And in chapter detail page template assuming context object name as current_chapter

<a href="{{current_chapter.get_next_chapter_url}}">Next Chapter</a>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文