2009-12-18 18 views
20

說我有按創建日期排序的照片列表如下:有沒有一種巧妙的方法使用Django ORM獲取上一個/下一個項目?

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

    class Meta: 
     ordering = ('-created',) 

我有一個任意的照片對象photo_x。有沒有一種簡單的方法可以在查詢集中按位置查找上一張和下一張照片?另外,如果我在開始/結束時我想環繞一下,如果只有1或2張照片,它不會失敗。

回答

32

你很幸運! Django默認創建get_next_by_fooget_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

+0

謝謝,我知道這樣的事情,我根本想不起來。 – 2009-12-19 01:56:56

+0

我很高興這是你正在尋找的。很高興能夠提供幫助。 – jathanism 2009-12-19 02:15:26

0

要jathanism答案,它有用,但get_next_by_FOOget_previous_by_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. 
2

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) 

如果你想訂購的領域的一些其他組合,只要通過查詢集:

photos = Photo.objects.order_by('title') 
photo = photos.get(...) 
next = next_in_order(photo, qs=photos) 
+1

包裝效果很好,謝謝分享。 – DragonBobZ 2017-07-13 18:59:42

相關問題