Django: limitar los resultados de la consulta


Respuestas:


304

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>]

Intenté esto en mongoDB y dice que SELECT no es compatible. ¿Cómo hacer esto en mongoDB?
winux

@winux Dado que esto es específico de Django, parece que es posible que deba considerar configurar Django para que funcione específicamente con bases de datos de tipo Mongo / NoSQL. Esa no es una configuración típica en mi experiencia, con respecto a la configuración estándar de Django ORM.
cobarde anónimo

38

En realidad, creo LIMIT 10que 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.


Tenga en cuenta que esto no funcionará para los conjuntos de consultas que también necesitan filtrado, ya que no puede filtrar después de segmentar.
Mike 'Pomax' Kamermans

2
Así que filtre primero que cortarlo. Gracias Davor por el enlace!
Vyachez

13

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.


Incluso esta solución no funciona con django> = 1.8 probado.
sonus21

3

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.


1

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.


1
Intenté esto y obtuve "La indexación negativa no es compatible".
bparker

@DarkCygnus Product.objects.filter(~Q(price=0))[-5:]me causa el mismo error: "No se admite la indexación negativa".
bersam

Esto no funciona en django en un conjunto de consultas: code.djangoproject.com/ticket/13089 Si convierte el conjunto de consultas a una lista, funcionará.
Valem
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.