2009-12-18 13 views
20

Powiedzmy mam listę zdjęć uporządkowanych według daty utworzenia, co następuje:Czy istnieje sprytny sposób na uzyskanie poprzedniego/następnego elementu za pomocą ORM Django?

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

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

Mam dowolny obiekt Photo photo_x. Czy istnieje łatwy sposób na znalezienie poprzedniego i następnego zdjęcia według pozycji w zapytaniu? Poza tym chciałbym zawinąć, jeśli jestem na początku/końcu i nie zawiodę, jeśli są to tylko 1 lub 2 zdjęcia.

Odpowiedz

32

Masz szczęście! Django domyślnie tworzy metody get_next_by_foo i get_previous_by_foo dla DateField & , o ile nie mają one null=True.

Na przykład:

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

A jeśli dojdziesz do końca zestawu to podniesie się DoesNotExist wyjątek, który można łatwo używać jako wyzwalacz, aby powrócić do początku zestawu:

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

Dalsze czytanie: Extra instance methods

+0

Dzięki, wiedziałem, że coś takiego istnieje, po prostu nie mogłem o tym myśleć. –

+0

Cieszę się, że tego właśnie szukałeś. Cieszę się, że mogę ci pomóc. – jathanism

0

Aby jathanism odpowiedź, jego przydatne, ale get_next_by_FOO i get_previous_by_FOO ignorować milisekund ... na przykład nie będzie działać dla obiektów utworzonych w pętli:

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 i get_previous_by_foo są poręczne, ale bardzo ograniczone - nie pomóc, jeśli jesteś zamawiania na więcej niż jednym polu lub polu innym niż data.

Napisałem django-next-prev jako bardziej ogólną implementację tego samego pomysłu. W twoim przypadku można po prostu to zrobić, skoro już ustawić kolejność w 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) 

Jeśli chciał zamówić na innej kombinacji pól, po prostu przekazać queryset:

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

Pakiet działa świetnie, dzięki za udostępnienie. – DragonBobZ

Powiązane problemy