代码之家  ›  专栏  ›  技术社区  ›  Jason Christa

有没有一种聪明的方法可以使用django orm获取上一个/下一个条目?

  •  20
  • Jason Christa  · 技术社区  · 16 年前

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

    class Photo(models.Model):
        title = models.Char()
        image = models.Image()
        created = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            ordering = ('-created',)
    

    我有一个任意的照片对象photo_x。有没有一个简单的方法可以通过在queryset中的位置找到上一张和下一张照片?另外,如果我是在开始/结束时,我想把它包起来,如果只有1或2张照片,我希望它不会失败。

    3 回复  |  直到 9 年前
        1
  •  32
  •   jathanism    16 年前

    你运气真好!Django创建 get_next_by_foo get_previous_by_foo 方法默认为 DateField 和; DateTimeField 只要他们没有 null=True .

    例如:

    >>> from foo.models import Request
    >>> r = Request.objects.get(id=1)
    >>> r.get_next_by_created()
    <Request: xyz246>
    

    如果你到了一套的末尾,它会 DoesNotExist 异常,可以很容易地用作返回集合开头的触发器:

    >>> r2 = r.get_next_by_created()
    >>> r2.get_next_by_created()
    ...
    DoesNotExist: Request matching query does not exist.
    

    进一步阅读: Extra instance methods

        2
  •  2
  •   Greg    9 年前

    get_next_by_foo和get_previous_by_foo很方便,但非常有限-如果您订购的是多个字段或非日期字段,它们对您没有帮助。

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

    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)
    

    如果您想订购其他字段组合,只需传递queryset:

    photos = Photo.objects.order_by('title')
    photo = photos.get(...)
    next = next_in_order(photo, qs=photos)
    
        3
  •  0
  •   Alex Isayko    9 年前

    对贾森主义的回答,是有用的,但是 接下一个 由Foo获取上一个 忽略毫秒…例如,对于在循环中创建的对象,它将不起作用:

    for i in range(100):
        Photo.objects.create(title='bla', ...)
    
    obj = Photo.objects.first()
    obj.get_previous_by_created()
    
    DoesNotExist: Photo matching query does not exist.