代码之家  ›  专栏  ›  技术社区  ›  Michael Dunn

如何从过滤有序的查询集中获取上一个和下一个对象?

  •  5
  • Michael Dunn  · 技术社区  · 15 年前

    我有一个基于模型对象的页面,我希望有到上一页和下一页的链接。我不喜欢当前的解决方案,因为它需要评估整个queryset(以获得 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是顺序的。

    3 回复  |  直到 15 年前
        1
  •  8
  •   T. Stone    15 年前

    听起来像是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 here here .

        2
  •  2
  •   Ihor Pomaranskyy    13 年前

    我不熟悉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
  •  1
  •   Greg    7 年前

    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)