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

问题描述 投票:0回答:7

我正在尝试获取漫画书的下一个和上一个对象。简单地更改 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]
django django-views
7个回答
60
投票

添加

order_by
子句以确保按
number
排序。

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

36
投票

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

所以这里的答案是这样的

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

Django 管理人员可以通过一些元类切割来做到这一点。


8
投票

如果需要查找按字段值排序的 nextprevious 对象,并且这些字段不是 Date* 类型,则查询会变得稍微复杂,因为:


对具有相同值的对象进行排序(受
    [:1]
  • 限制)将始终对多个对象产生相同的结果;
    对象本身可以包含在结果集中。
  • 这里的查询集也考虑了主键以产生正确的结果(假设 OP 中的
number

参数不是唯一的,并省略

title
参数,因为它与示例无关):

上一篇:

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())



0
投票


0
投票
请注意,不要使用
object.get(pk=object.pk + 1)

这些类型的东西,如果删除该 pk 处的对象,则会发生

IntegrityError
,因此始终使用查询集

对于访客:

''' Useage ''' """ # Declare our item store = Store.objects.get(pk=pk) # Define our models stores = Store.objects.all() # Ask for the next item new_store = get_next_or_prev(stores, store, 'next') # If there is a next item if new_store: # Replace our item with the next one store = new_store """ ''' Function ''' def get_next_or_prev(models, item, direction): ''' Returns the next or previous item of a query-set for 'item'. 'models' is a query-set containing all items of which 'item' is a part of. direction is 'next' or 'prev' ''' getit = False if direction == 'prev': models = models.reverse() for m in models: if getit: return m if item == m: getit = True if getit: # This would happen when the last # item made getit True return models[0] return False

原作者

使用方法

# you MUST call order by to pass in an order, otherwise QuerySet.reverse will not work qs = Model.objects.all().order_by('pk') q = qs[0] prev = get_next_or_prev(qs, q, 'prev') next = get_next_or_prev(qs, q, 'next')



0
投票

next_post = Blog.objects.filter(date__lte=self.object.date, published=True).exclude(id=self.object.id).order_by('-date').first() next_post = next_post if next_post else Blog.objects.filter(published=True).first() previous_post = Blog.objects.filter(date__gte=self.object.date, published=True).exclude(id=self.object.id).order_by('date').first() previous_post = previous_post if previous_post else Blog.objects.filter(published=True).last()



-3
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.