有没有一种聪明的方法来使用Django ORM获取上一个/下一个项目?

Jas*_*sta 20 python django django-models

假设我有按创建日期排序的照片列表,如下所示:

class Photo(models.Model):
    title = models.Char()
    image = models.Image()
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ('-created',)
Run Code Online (Sandbox Code Playgroud)

我有一个任意的Photo对象photo_x.有没有一种简单的方法可以在查询集中按位置查找上一张和下一张照片?另外,如果我只是1张或2张照片,我想在开始/结束时使用它并且不会失败.

jat*_*ism 32

你很幸运!Django 默认为&创建get_next_by_fooget_previous_by_foo方法,只要它们没有.DateFieldDateTimeFieldnull=True

例如:

>>> from foo.models import Request
>>> r = Request.objects.get(id=1)
>>> r.get_next_by_created()
<Request: xyz246>
Run Code Online (Sandbox Code Playgroud)

如果你到达一个集合的末尾,它将引发一个DoesNotExist异常,你可以很容易地将其作为触发器返回到集合的开头:

>>> r2 = r.get_next_by_created()
>>> r2.get_next_by_created()
...
DoesNotExist: Request matching query does not exist.
Run Code Online (Sandbox Code Playgroud)

进一步阅读:额外的实例方法


Gre*_*reg 5

get_next_by_foo 和 get_previous_by_foo 很方便,但非常有限 - 如果您在多个字段或非日期字段上进行排序,它们对您没有帮助。

我编写了django-next-prev作为同一想法的更通用的实现。在您的情况下,您可以这样做,因为您已经在元中设置了顺序:

from next_prev import next_in_order, prev_in_order
from .models import Photo

photo = Photo.objects.get(...)
next = next_in_order(photo)
prev = prev_in_order(photo)
Run Code Online (Sandbox Code Playgroud)

如果您想对其他字段组合进行排序,只需传递查询集:

photos = Photo.objects.order_by('title')
photo = photos.get(...)
next = next_in_order(photo, qs=photos)
Run Code Online (Sandbox Code Playgroud)