2011-07-04 19 views
107

quiero tomar los últimos 10 casos de un modelo y tener este código:Django - Resultados de la consulta limitar

Model.objects.all().order_by('-id')[:10] 

¿Es cierto que en primer lugar, recoger todas las instancias, y luego tomar sólo 10 los últimos? ¿Hay algún método más efectivo?

+4

https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets –

+0

Derecha. Me perdí esto en alguna parte. – krzyhub

Respuesta

184

Django querysets are holgazán. Eso significa que una consulta golpeará la base de datos solo cuando específicamente solicite el resultado.

De modo que 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>] 
22

En realidad, creo que el LIMIT 10 se emitirá a la base de datos, por lo que el corte no ocurriría en Python, sino en la base de datos.

Consulte limiting-querysets para obtener más información.

-3

No, no es cierto, como se explica claramente en la documentación.

8

Parece que la solución de la cuestión no funciona con Django 1.7 más y genera un error: "No se puede cambiar el orden de una consulta una vez que una rebanada ha sido tomada"

De acuerdo con la documentación https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets forzando el parámetro "paso" de la sintaxis de corte de Python evalúa la consulta. Funciona de la siguiente manera:

Model.objects.all().order_by('-id')[:10:1] 

Todavía me pregunto si se ejecuta el límite en rodajas de SQL o Python devuelto toda la matriz resultante. No es bueno recuperar listas enormes para la memoria de la aplicación.

+0

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

-8

Esto no es lo que realmente sucede. Django NO busca solo los resultados necesarios. Django cargaría la tabla de la base de datos completa (que es una tarea de identificación [identificación que hacer) y le devolverá solo los últimos 10 registros.

Lo he confirmado ejecutando MOSTRAR LISTA DE PROCESOS COMPLETOS en el servidor MySQL, y la consulta NO tiene una cláusula LIMIT.

Django NO es una buena opción si va a desarrollar una aplicación grande que requiera una gran escalabilidad.

+3

Proporcione detalles adicionales para probar esto. La respuesta mejor calificada muestra que lo que Django registra como ejecutando contiene el límite. Acabo de verificar que esto sigue siendo cierto para Django 1.10. No pude mostrar la lista de procesos completa porque la consulta fue tan breve que no se mostró. Activar registros de consultas como se sugiere http://stackoverflow.com/questions/650238/how-to-show-the-last-queries-executed-on-mysql, MySql (o MariaDB para ser específicos) muestra que la consulta contiene el cláusula de límite. ¿Acaso no está haciendo su consulta de modo que pueda cargarse de forma diferida? – Foon

Cuestiones relacionadas