2009-12-18 12 views
20

Decir que tengo una lista de fotos ordenadas por fecha de creación, de la siguiente manera:¿Existe alguna manera inteligente de obtener el artículo anterior/siguiente con el ORM de Django?

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

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

Tengo una photo_x objeto Photo arbitraria. ¿Hay alguna manera fácil de encontrar las fotos anteriores y siguientes por posición en el conjunto de preguntas? Además, me gustaría envolverme si estoy al principio/final y que no falle si solo hay 1 o 2 fotos.

Respuesta

32

¡Estás de enhorabuena! Django crea los métodos get_next_by_foo y get_previous_by_foo de forma predeterminada para DateField & DateTimeField, siempre que no tengan null=True.

Por ejemplo:

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

Y si se llega al final de un conjunto que provocará una excepción DoesNotExist, que se puede utilizar fácilmente como un disparador para volver al comienzo de la serie:

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

Más información: Extra instance methods

+0

Gracias, sabía que algo así existía. No podía pensar en eso. –

+0

Estoy feliz de que esto sea lo que estabas buscando. Me alegro de poder ayudar. – jathanism

0

para responder a jathanism, su útiles, pero get_next_by_FOO y get_previous_by_FOO ignorar milisegundos ... por ejemplo, no funcionará para los objetos creados en bucle:

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 y get_previous_by_foo son muy útiles, pero muy limitado - no te ayudan si estás pidiendo en más de un campo, o en un campo sin fecha.

Escribí django-next-prev como una implementación más genérica de la misma idea. En su caso, usted puede simplemente hacer esto, ya que ha establecido el orden en su 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) 

Si quisiera ordenar en alguna otra combinación de campos, sólo tiene que pasar la queryset:

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

El paquete funciona muy bien, gracias por compartirlo. – DragonBobZ

Cuestiones relacionadas