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.
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"
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.
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.
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á.
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.
fuente
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.
fuente
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:
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.
fuente
Si. Si desea obtener un subconjunto limitado de objetos, puede hacerlo con el siguiente código:
Ejemplo:
El principio 0 es opcional, entonces
El código anterior devuelve las primeras 10 instancias.
fuente
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 usoorder_by('-id')
con el-
de revertir los elementos.fuente
Product.objects.filter(~Q(price=0))[-5:]
me causa el mismo error: "No se admite la indexación negativa".