【问题标题】:How can I get previous and next objects from a filtered, ordered queryset?如何从过滤的有序查询集中获取上一个和下一个对象?
【发布时间】:2010-12-14 03:00:22
【问题描述】:

我有一个基于模型对象的页面,我希望有指向上一页和下一页的链接。我不喜欢我当前的解决方案,因为它需要评估整个查询集(以获取ids 列表),然后再评估两个get 查询。肯定有某种方法可以一次性完成吗?

def get_prev_and_next_page(current_page):
    ids = list(Page.objects.values_list("id", flat=True))
    current_idx = ids.index(current_page.id)
    prev_page = Page.objects.get(id=ids[current_idx-1])
    try:
        next_page = Page.objects.get(id=ids[current_idx+1])
    except IndexError:
        next_page = Page.objects.get(id=ids[0])
    return (prev_page, next_page)

排序顺序是在模型中定义的,所以这里不必处理,但请注意不能假设 id 是连续的。

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    听起来像 Paginator 设置为阈值 1 会做得很好。

    # Full query set...
    pages = Page.objects.filter(column=somevalue)
    p = Paginator(pages, 1)
    
    # Where next page would be something like...
    if p.has_next():
         p.page(p.number+1)
    

    Documentation herehere

    【讨论】:

    • 谢谢,我隐约知道 Paginator,但没有意识到我可以这样使用它(即阈值为 1,实际上只是将查询集包装在 Paginator 对象中has_next()has_previous() 方法)。唯一缺少的是我没有从分页器范围的开头开始,但看起来我可以用p.object_list.index(start_page) 得到这个。
    • 这对我来说效果不佳。 Paginator 类真的不是用来遍历对象的。
    【解决方案2】:

    我是 Python 和 Django 的新手,所以我的代码可能不是最佳的,但请检查一下:

    def get_prev_and_next_items(target, items):
        ''' To get previous and next objects from QuerySet '''
        found = False
        prev = None
        next = None
        for item in items:
            if found:
                next = item
                break
            if item.id == target.id:
                found = True
                continue
            prev = item
        return (prev, next)
    

    考虑到这样的事情:

    def organisation(request, organisation_id):
        organisation = Organisation.objects.get(id=organisation_id)
        ...
        prev, next = get_prev_and_next_items(organisation, Organisation.objects.all().order_by('type'))
        ...
        return render_to_response('reference/organisation/organisation.html', {
            'organisation': organisation,
            'prev': prev,
            'next': next,
        })
    

    绝对不是“重”查询集的最佳选择,但在大多数情况下,它就像一个魅力。 :)

    【讨论】:

      【解决方案3】:

      查看django-next-prev,我写它是为了解决这个确切的问题。在这种情况下:

      from next_prev import next_in_order, prev_in_order
      
      def get_prev_and_next_page(current_page):
          page_qs = Page.objects.all()  # this could be filtered, or ordered
          prev_page = prev_in_order(current_page, page_qs)
          next_page = next_in_order(current_page, page_qs)
          return (prev_page, next_page)
      

      【讨论】:

      • 如果发现问题,请在 repo 上提出问题
      猜你喜欢
      • 2019-01-30
      • 1970-01-01
      • 2021-08-24
      • 2018-04-25
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2018-07-07
      相关资源
      最近更新 更多