在Django中获取下一个和上一个对象

时间:2011-05-16 18:28:12

标签: django django-views

我正在尝试获取漫画书问题的下一个和前一个对象。简单地更改ID号或过滤添加日期是行不通的,因为我没有按顺序添加问题。

这是我的视图设置方式,它适用于prev_issue并且确实返回上一个对象,但它返回next_issue的最后一个对象,我不知道为什么。

def issue(request, issue_id):
issue = get_object_or_404(Issue, pk=issue_id)
title = Title.objects.filter(issue=issue)
prev_issue = Issue.objects.filter(title=title).filter(number__lt=issue.number)[0:1]
next_issue = Issue.objects.filter(title=title).filter(number__gt=issue.number)[0:1]

5 个答案:

答案 0 :(得分:38)

添加order_by子句以确保按number订购。

next_issue = Issue.objects.filter(title=title, number__gt=issue.number).order_by('number').first()

答案 1 :(得分:25)

我知道这有点晚了,但对于其他任何人来说,django确实有更好的方法来做到这一点,请参阅https://docs.djangoproject.com/en/1.7/ref/models/instances/#django.db.models.Model.get_previous_by_FOO

所以这里的答案就像是

next_issue = Issue.get_next_by_number(issue, title=title)

Django经理用一点元类切割器来做到这一点。

答案 2 :(得分:5)

如果需要找到下一个以前的对象,按字段值排序可以相等且这些字段不是在Date*类型中,查询稍微复杂,因为:

  • 对具有相同值的对象进行排序[:1]将始终为多个对象生成相同的结果;
  • 对象本身可以包含在结果集中。

这里的查询集还考虑了产生正确结果的主键(假设来自OP的number参数不是唯一的,并省略了title参数,因为它&#39 ;与例子无关):

<强>上:

prev_issue = (Issue.objects
    .filter(number__lte=issue.number, id__lt=instance.id)
    .exclude(id=issue.id)
    .order_by('-number', '-id')
    .first())

下一步:

next_issue = (Issue.objects
    .filter(number__gte=issue.number, id__gt=instance.id)
    .exclude(id=issue.id)
    .order_by('number', 'id')
    .first())

答案 3 :(得分:0)

from functools import partial, reduce
from django.db import models


def next_or_prev_instance(instance, qs=None, prev=False, loop=False):

    if not qs:
        qs = instance.__class__.objects.all()

    if prev:
        qs = qs.reverse()
        lookup = 'lt'
    else:
        lookup = 'gt'

    q_list = []
    prev_fields = []

    if qs.query.extra_order_by:
        ordering = qs.query.extra_order_by
    elif qs.query.order_by:
        ordering = qs.query.order_by
    elif qs.query.get_meta().ordering:
        ordering = qs.query.get_meta().ordering
    else:
        ordering = []

    ordering = list(ordering)

    if 'pk' not in ordering and '-pk' not in ordering:
        ordering.append('pk')
        qs = qs.order_by(*ordering)

    for field in ordering:
        if field[0] == '-':
            this_lookup = (lookup == 'gt' and 'lt' or 'gt')
            field = field[1:]
        else:
            this_lookup = lookup
        q_kwargs = dict([(f, get_model_attr(instance, f))
                         for f in prev_fields])
        key = "%s__%s" % (field, this_lookup)
        q_kwargs[key] = get_model_attr(instance, field)
        q_list.append(models.Q(**q_kwargs))
        prev_fields.append(field)
    try:
        return qs.filter(reduce(models.Q.__or__, q_list))[0]
    except IndexError:
        length = qs.count()
        if loop and length > 1:
            return qs[0]
    return None


next_instance = partial(next_or_prev_instance, prev=False)
prev_instance = partial(next_or_prev_instance, prev=True)

答案 4 :(得分:-1)

next_obj_id = int(current_obj_id) + 1 next_obj = Model.objects.filter(id=next_obj_id).first()

prev_obj_id= int(current_obj_id) - 1 prev_obj = Model.objects.filter(id=prev_obj_id).first()

#你没有什么可失去的...这对我有用