Quiero tomar las últimas 10 instancias de un modelo y tener este código:
Model.objects.all().order_by('-id')[:10]
¿Es cierto que primero recoge todas las instancias y luego toma solo 10 últimas? ¿Hay algún método más efectivo?
Quiero tomar las últimas 10 instancias de un modelo y tener este código:
Model.objects.all().order_by('-id')[:10]
¿Es cierto que primero recoge todas las instancias y luego toma solo 10 últimas? ¿Hay algún método más efectivo?
Respuestas:
Los conjuntos de consultas de Django son vagos. Eso significa que una consulta llegará a la base de datos solo cuando solicite específicamente el resultado.
Entonces, hasta que imprima o realmente use el resultado de una consulta, puede filtrar aún más sin acceso a la base de datos.
Como puede ver a continuación, su código solo ejecuta una consulta sql para obtener solo los últimos 10 elementos.
In [19]: import logging
In [20]: l = logging.getLogger('django.db.backends')
In [21]: l.setLevel(logging.DEBUG)
In [22]: l.addHandler(logging.StreamHandler())
In [23]: User.objects.all().order_by('-id')[:10]
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]
En realidad, creo LIMIT 10
que se emitirá a la base de datos, por lo que no se producirá el corte en Python sino en la base de datos.
Consulte la limitación de conjuntos de consultas para obtener más información.
Parece que la solución en la pregunta ya no funciona con Django 1.7 y genera un error: "No se puede reordenar una consulta una vez que se ha tomado un segmento"
De acuerdo con la documentación https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets que obliga al parámetro "paso" de la sintaxis de corte Python evalúa la consulta. Funciona de esta manera:
Model.objects.all().order_by('-id')[:10:1]
Aún así, me pregunto si el límite se ejecuta en secciones de SQL o Python que devuelve toda la matriz de resultados. No es bueno recuperar grandes listas en la memoria de la aplicación.
Si. Si desea obtener un subconjunto limitado de objetos, puede hacerlo con el siguiente código:
Ejemplo:
obj=emp.objects.all()[0:10]
El principio 0 es opcional, entonces
obj=emp.objects.all()[:10]
El código anterior devuelve las primeras 10 instancias.
Como una adición y observación a las otras respuestas útiles, vale la pena notar que, en realidad, hacer un [:10]
corte devolverá los primeros 10 elementos de la lista , no los últimos 10 ...
Para obtener los últimos 10 debe hacer en su [-10:]
lugar (ver aquí ). Esto le ayudará a evitar el uso order_by('-id')
con el -
de revertir los elementos.
Product.objects.filter(~Q(price=0))[-5:]
me causa el mismo error: "No se admite la indexación negativa".