QuerySet¶Este documento describe los detalles de la API QuerySet. Se basa en el material presentado en las guías model y database query, por lo que probablemente querrás leer y entender esos documentos antes de leer este uno.
A lo largo de esta referencia utilizaremos los modelos de ejemplo del blog presentados en la guía database query guide.
Internamente, se puede construir, filtrar, cortar y pasar en general un QuerySet alrededor sin que realmente se produzca actividad en la base de datos. No ocurre ninguna actividad en la base de datos hasta que hagas algo para evaluar el conjunto de consultas.
Puedes evaluar un QuerySet de las siguientes maneras:
Iteración. Un QuerySet es iterable, y ejecuta su consulta de base de datos la primera vez que iteras sobre él. Por ejemplo, esto imprimirá el titular de todos los registros en la base de datos:
for e in Entry.objects.all():
print(e.headline)
La traducción de los textos es la siguiente:
Iteración asíncrona. Un QuerySet también se puede iterar sobre utilizando async for:
async for e in Entry.objects.all():
results.append(e)
Ambos iteradores síncronos y asíncronos de QuerySets comparten el mismo caché subyacente.
Slicing. Como se explica en Limitación de QuerySet, un QuerySet se puede recortar, utilizando la sintaxis de recorte de arrays de Python. Recortar un QuerySet no evaluado suele devolver otro QuerySet no evaluado, pero Django ejecutará la consulta de base de datos si utiliza el parámetro «step» de la sintaxis de recorte y devolverá una lista. Recortar un QuerySet que ha sido evaluado también devuelve una lista.
También ten en cuenta que aunque recortar un QuerySet no evaluado devuelve otro QuerySet no evaluado, modificarlo posteriormente (por ejemplo, agregando más filtros o modificando el ordenamiento) no está permitido, ya que eso no se traduce bien a SQL y tampoco tendría un significado claro.
Pickling/Caching. Consulta la siguiente sección para obtener detalles de lo que implica cuando pickling QuerySets. La cosa importante para los propósitos de esta sección es que los resultados se leen desde la base de datos.
repr(). Un QuerySet se evalúa cuando llamas a repr() en él. Esto está diseñado para conveniencia en el intérprete interactivo de Python, así que puedes ver tus resultados inmediatamente al usar la API interactivamente.
len(). Un QuerySet se evalúa cuando llamas a len() en él. Esto, como podrías esperar, devuelve la longitud de la lista de resultados.
Nota: Si solo necesitas determinar el número de registros en el conjunto (y no necesitas los objetos reales), es mucho más eficiente manejar un recuento a nivel de base de datos utilizando SQL’s SELECT COUNT(*). Django proporciona un método count() para precisamente este motivo.
list(). Forza la evaluación de un QuerySet llamando a list() en él. Por ejemplo:
entry_list = list(Entry.objects.all())
bool(). Pruebaando un QuerySet en un contexto booleano, como utilizando bool(), or, and o una sentencia if, causará que la consulta se ejecute. Si hay al menos un resultado, el QuerySet es True, de lo contrario False. Por ejemplo:
if Entry.objects.filter(headline="Test"):
print("There is at least one Entry with the headline Test")
Nota: si solo deseas determinar si existe al menos un resultado (y no necesitas los objetos reales), es más eficiente utilizar exists().
QuerySets¶Si pickle un QuerySet, esto forzará a cargar todos los resultados en memoria antes del plegado. El plegado se utiliza normalmente como precursor de la caché y cuando el conjunto de resultados cargados es reutilizado, quieres que los resultados ya estén presentes y listos para su uso (la lectura desde la base de datos puede tardar algún tiempo, lo que defrauda el propósito de la caché). Esto significa que cuando desplegas un QuerySet, contiene los resultados en el momento en que se plegó, más que los resultados que actualmente están en la base de datos.
Si solo deseas plegar la información necesaria para recrear el QuerySet desde la base de datos en algún momento posterior, plega el atributo query del QuerySet. Puedes luego recrear el conjunto original de resultados (sin cargar ningún resultado) utilizando algún código como este:
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
El atributo query es un objeto opaco. Representa la construcción interna de la consulta y no forma parte de la API pública. Sin embargo, es seguro (y completamente soportado) plegar y desplegar el contenido del atributo según se describe aquí.
Restricciones en QuerySet.values_list()
Si recreas QuerySet.values_list() utilizando el atributo query plegado, se convertirá a QuerySet.values():
>>> import pickle
>>> qs = Blog.objects.values_list("id", "name")
>>> qs
<QuerySet [(1, 'Beatles Blog')]>
>>> reloaded_qs = Blog.objects.all()
>>> reloaded_qs.query = pickle.loads(pickle.dumps(qs.query))
>>> reloaded_qs
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
Aquí está la declaración formal de un QuerySet:
Normalmente, cuando interactuarás con un QuerySet, lo harás mediante chaining filters. Para que esto funcione, la mayoría de los métodos del QuerySet devuelven nuevos conjuntos de consultas. Estos métodos se cubren en detalle más adelante en esta sección.
La clase QuerySet tiene las siguientes atributos públicos que puedes utilizar para introspección:
True si el QuerySet está ordenado — es decir, tiene una cláusula order_by() o un ordenamiento predeterminado en el modelo. False en caso contrario.
Nota
El parámetro query a QuerySet existe para que las subclases de consultas especializadas puedan reconstruir el estado de la consulta interna. El valor del parámetro es una representación opaca de ese estado de consulta y no forma parte de una API pública.
QuerySets¶Django proporciona una variedad de métodos de refinamiento de QuerySet que modifican ya sea los tipos de resultados devueltos por el QuerySet o la forma en que se ejecuta su consulta SQL.
Nota
Estos métodos no ejecutan consultas a la base de datos, por lo tanto son seguros para ejecutar en código asíncrono, y no tienen versiones asíncronas separadas.
filter()¶Devuelve un nuevo conjunto de consultas (QuerySet) que contiene objetos que coinciden con los parámetros de búsqueda dados.
Los parámetros de búsqueda (**kwargs) deben estar en el formato descrito en Búsquedas de campos a continuación. Los múltiples parámetros se unen mediante AND en la sentencia SQL subyacente.
Si necesitas ejecutar consultas más complejas (por ejemplo, consultas con declaraciones OR), puedes utilizar objetos Q (*args).
exclude()¶Devuelve un nuevo conjunto de consultas (QuerySet) que contiene objetos que no coinciden con los parámetros de búsqueda dados.
Los parámetros de búsqueda (**kwargs) deben estar en el formato descrito en Búsquedas de campos a continuación. Los múltiples parámetros se unen mediante AND en la sentencia SQL subyacente, y todo está encerrado dentro de una NOT().
Este ejemplo excluye todos los registros cuya fecha de publicación (pub_date) es posterior a 2005-1-3 Y cuyo título (headline) es «Hola»:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline="Hello")
En términos de SQL, eso evalúa a:
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
Este ejemplo excluye todos los registros cuya fecha de publicación (pub_date) es posterior a 2005-1-3 O cuyo título (headline) es «Hola»:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline="Hello")
En términos de SQL, eso evalúa a:
SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'
Tenga en cuenta que el segundo ejemplo es más restrictivo.
Si necesitas ejecutar consultas más complejas (por ejemplo, consultas con declaraciones OR), puedes utilizar objetos Q (*args).
annotate()¶Anota cada objeto en el conjunto de consultas con la lista proporcionada de expresiones de consulta o objetos de consulta o ~django.db.models.Q . Cada objeto puede estar anotado con:
un valor simple, a través de Value();
una referencia a un campo en el modelo (o cualquier modelo relacionado), a través de F();
un booleano, a través de Q(); o
el resultado de una expresión de agregación (promedios, sumas, etc.) calculada sobre los objetos que están relacionados con los objetos en el conjunto de consultas.
Cada argumento de annotate() es una anotación que se agregará a cada objeto en el conjunto de consultas que se devuelve.
Las funciones de agregación proporcionadas por Django se describen en Funciones de Agregación a continuación.
Las anotaciones especificadas utilizando argumentos de palabra clave utilizarán la palabra clave como alias para la anotación. Los argumentos anónimos tendrán un alias generado basado en el nombre de la función de agregación y el campo del modelo que se está agrupando. Solo las expresiones de agregación que refieren a un solo campo pueden ser argumentos anónimos. Todo lo demás debe ser un argumento de palabra clave.
Por ejemplo, si estabas manipulando una lista de blogs, puede que desees determinar cuántos entradas se han hecho en cada blog:
>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count("entry"))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42
El modelo Blog no define un atributo entry__count por sí solo, pero utilizando una argumento de palabra clave para especificar la función agregada, puedes controlar el nombre de la anotación:
>>> q = Blog.objects.annotate(number_of_entries=Count("entry"))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42
Para una discusión en profundidad sobre la agregación, consulte la guía del tema sobre Agregación.
alias()¶Igual que annotate(), pero en lugar de anotar objetos en el QuerySet, guarda la expresión para su uso posterior con otros métodos QuerySet. Esto es útil cuando el resultado de la expresión misma no se necesita, pero se utiliza para filtrado, ordenación o como parte de una expresión compleja. No seleccionar el valor innecesario elimina trabajo redundante del servidor que debería resultar en mejor rendimiento.
Por ejemplo, si deseas encontrar blogs con más de 5 entradas, pero no estás interesado en el número exacto de entradas, podrías hacer esto:
>>> from django.db.models import Count
>>> blogs = Blog.objects.alias(entries=Count("entry")).filter(entries__gt=5)
alias() se puede utilizar conjuntamente con annotate(), exclude(), filter(), order_by() y update(). Para usar expresiones aliasadas con otros métodos (por ejemplo, aggregate()), debes promoverla a una anotación:
Blog.objects.alias(entries=Count("entry")).annotate(
entries=F("entries"),
).aggregate(Sum("entries"))
filter() y order_by() pueden tomar expresiones directamente, pero la construcción de expresiones y su uso a menudo no ocurre en el mismo lugar (por ejemplo, QuerySet método crea expresiones, para su uso posterior en vistas). alias() permite construir expresiones complejas incrementalmente, posiblemente abarcando múltiples métodos y módulos, hacer referencia a las partes de la expresión por sus alias y solo utilizar annotate() para el resultado final.
order_by()¶Por defecto, los resultados devueltos por un QuerySet están ordenados según la tupla de ordenamiento dada por la opción ordering en el Meta del modelo. Puedes sobrescribir esto en una base por QuerySet utilizando el método order_by.
Ejemplo:
Entry.objects.filter(pub_date__year=2005).order_by("-pub_date", "headline")
El resultado anterior estará ordenado por pub_date descendente, luego por headline ascendente. El signo negativo frente a "-pub_date" indica orden descendente. Se implica orden ascendente. Para ordenar al azar, utiliza "?", como se muestra:
Entry.objects.order_by("?")
Nota: consultas con order_by('?') pueden ser costosas y lentas, dependiendo del motor de base de datos que estés utilizando.
Para ordenar por un campo de un modelo diferente, utiliza la misma sintaxis que cuando estás consultando a través de relaciones entre modelos. Es decir, el nombre del campo, seguido de dos subrayados (__), seguido del nombre del campo en el nuevo modelo, y así sucesivamente para tantos modelos como desees unir. Por ejemplo:
Entry.objects.order_by("blog__name", "headline")
Si intentas ordenar por un campo que es una relación con otro modelo, Django utilizará la ordenación predeterminada en el modelo relacionado o ordenará por la clave primaria del modelo relacionado si no se especifica Meta.ordering. Por ejemplo, dado que el modelo Blog no tiene ninguna ordenación predeterminada especificada:
Entry.objects.order_by("blog")
…es idéntico a:
Entry.objects.order_by("blog__id")
Si Blog tuviera ordering = ['name'], entonces la primera consulta de conjunto sería idéntica a:
Entry.objects.order_by("blog__name")
Puedes ordenar también por expresiones de consulta :doc:`query expressions <query_expressions> llamando a :meth:`~.Expression.asc o :meth:`~.Expression.desc en la expresión:
Entry.objects.order_by(Coalesce("summary", "headline").desc())
asc() y desc() tienen argumentos (nulls_first y nulls_last) que controlan cómo se ordenan los valores nulos.
Ten cuidado al ordenar por campos en modelos relacionados si también estás utilizando distinct(). Consulta la nota en distinct() para una explicación de cómo el ordenamiento de los modelos relacionados puede cambiar los resultados esperados.
Nota
Es permitido especificar un campo de valor múltiple para ordenar los resultados por (por ejemplo, un campo ManyToManyField o la relación inversa de un campo ForeignKey).
Considera este caso:
class Event(Model):
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
related_name="children",
)
date = models.DateField()
Event.objects.order_by("children__date")
Los resultados podrían contener múltiples datos de ordenamiento para cada Event; cada Event con múltiples children se devolverá varias veces en la nueva QuerySet que crea order_by(). En otras palabras, usar order_by() en la QuerySet podría devolver más elementos de los que estabas trabajando al principio - lo cual es probablemente ni esperado ni útil.
Ten cuidado cuando uses un campo con múltiples valores para ordenar los resultados. Si puedes estar seguro de que habrá solo un dato de ordenamiento para cada uno de los elementos que estás ordenando, esta aproximación no debería presentar problemas. Si no, asegúrate de que los resultados sean lo que esperas.
No hay forma de especificar si el ordenamiento debe ser sensible a la casilla. Con respecto a la sensibilidad a la casilla, Django ordenará los resultados según cómo normalmente ordena su backend de base de datos.
Puedes ordenar por un campo convertido a minúsculas con Lower que logrará el ordenamiento consistente en caso:
Entry.objects.order_by(Lower("headline").desc())
Si no quieres aplicar ningún ordenamiento a una consulta, ni siquiera el ordenamiento predeterminado, llama a order_by() sin parámetros.
Puedes saber si una consulta está ordenada o no comprobando la atributo QuerySet.ordered que será True si la QuerySet ha sido ordenada de alguna manera.
Cada llamada a order_by() limpiará cualquier ordenamiento previo. Por ejemplo, esta consulta se ordenará por pub_date y no por headline:
Entry.objects.order_by("headline").order_by("pub_date")
Advertencia
La ordenación no es una operación gratuita. Cada campo que agregues a la ordenación incurre en un costo para tu base de datos. Cada clave foránea que agregues incluirá implícitamente todas sus ordenaciones por defecto también.
Si una consulta no tiene una ordenación especificada, los resultados se devuelven desde la base de datos en un orden no especificado. Una particular ordenación está garantizada solo cuando se ordena por un conjunto de campos que identifiquen únicamente cada objeto en los resultados. Por ejemplo, si un campo name no es único, ordenar por él no garantiza que los objetos con el mismo nombre siempre aparezcan en el mismo orden.
reverse()¶Utiliza el método reverse() para revertir el orden en que los elementos de una queryset se devuelven. Llamar a reverse() una segunda vez restaura el ordenamiento a la dirección normal.
Para recuperar los «últimos» cinco elementos en una queryset, podrías hacer esto:
my_queryset.reverse()[:5]
Note that this is not quite the same as slicing from the end of a sequence in
Python. The above example will return the last item first, then the
penultimate item and so on. If we had a Python sequence and looked at
seq[-5:], we would see the fifth-last item first. Django doesn’t support
that mode of access (slicing from the end), because it’s not possible to do it
efficiently in SQL.
También es importante tener en cuenta que reverse() debe llamarse generalmente solo sobre un conjunto de consultas que tenga una ordenación definida (por ejemplo, cuando se consulta contra un modelo que define una ordenación por defecto o cuando se utiliza order_by()). Si no hay tal ordenación definida para un conjunto de consultas dado, llamar a reverse() sobre él no tiene ningún efecto real (la ordenación estaba indefinida antes de llamar a reverse(), y seguirá siendo indefinida después).
distinct()¶Devuelve un nuevo conjunto de consultas que utiliza SELECT DISTINCT en su consulta SQL. Esto elimina filas duplicadas de los resultados de la consulta.
Por defecto, un conjunto de consultas no eliminará filas duplicadas. En la práctica, esto es raramente un problema, porque las consultas simples como Blog.objects.all() no introducen la posibilidad de filas de resultado duplicadas. Sin embargo, si su consulta abarca varias tablas, es posible obtener resultados duplicados cuando se evalúa un conjunto de consultas. Eso es cuando usarías distinct().
Nota
Cualquier campo utilizado en una llamada a order_by() está incluido en las columnas SQL SELECT. Esto puede llevar a resultados inesperados cuando se utiliza conjuntamente con distinct(). Si ordena por campos de un modelo relacionado, esos campos se agregarán a las columnas seleccionadas y pueden hacer que filas que de otro modo parecen duplicadas aparezcan como distintas. Dado que las columnas adicionales no aparecen en los resultados devueltos (están allí solo para apoyar la ordenación), a veces parece que se están devolviendo resultados no distinguidos.
De manera similar, si utilizas una consulta values() para restringir las columnas seleccionadas, los campos utilizados en cualquier llamada a order_by() (o ordenación por defecto del modelo) seguirán involucrados y pueden afectar la unicidad de los resultados.
La moraleja aquí es que si estás utilizando distinct() ten cuidado con la ordenación por modelos relacionados. De manera similar, cuando se utiliza distinct() y values() juntas, ten cuidado al ordenar por campos no incluidos en la llamada a values().
Sólo en PostgreSQL, puedes pasar argumentos posicionales (*fields) para especificar los nombres de los campos a los que se debe aplicar DISTINCT. Esto se traduce en una consulta SQL SELECT DISTINCT ON. Aquí está la diferencia. Para un llamado normal a distinct(), la base de datos compara cada campo en cada fila al determinar qué filas son distintas. Para un llamado a distinct() con nombres de campos especificados, la base de datos solo comparará los nombres de campos especificados.
Nota
Cuando especificas nombres de campos, debes proporcionar una order_by() en el conjunto de consultas y los campos en order_by() deben comenzar con los campos en distinct(), en el mismo orden.
For example, SELECT DISTINCT ON (a) te da la primera fila para cada valor en la columna a. Si no especificas un orden, obtendrás alguna fila arbitraria.
Ejemplos (solo funcionarán en PostgreSQL):
>>> Author.objects.distinct()
[...]
>>> Entry.objects.order_by("pub_date").distinct("pub_date")
[...]
>>> Entry.objects.order_by("blog").distinct("blog")
[...]
>>> Entry.objects.order_by("author", "pub_date").distinct("author", "pub_date")
[...]
>>> Entry.objects.order_by("blog__name", "mod_date").distinct("blog__name", "mod_date")
[...]
>>> Entry.objects.order_by("author", "pub_date").distinct("author")
[...]
Nota
Ten en cuenta que order_by() utiliza cualquier ordenación relacionada por defecto que se haya definido. Es posible que debas ordenar explícitamente por la relación _id o el campo referenciado para asegurarte de que las expresiones DISTINCT ON coincidan con las del principio de la cláusula ORDER BY. Por ejemplo, si el modelo Blog definió un ordering por name:
Entry.objects.order_by("blog").distinct("blog")
…no funcionaría porque la consulta estaría ordenada por blog__name, lo que no coincidiría con la expresión DISTINCT ON. Tendrías que ordenar explícitamente por el campo de relación _id (blog_id en este caso) o el referenciado (blog__pk) para asegurarte de que ambas expresiones coincidan.
values()¶Devuelve un conjunto de consultas QuerySet que devuelve diccionarios, en lugar de instancias de modelo, cuando se utiliza como iterable.
Cada uno de esos diccionarios representa un objeto, con las claves correspondientes a los nombres de atributo de objetos de modelo.
Este ejemplo compara los diccionarios de values() con las instancias de modelo normales:
# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith="Beatles")
<QuerySet [<Blog: Beatles Blog>]>
# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith="Beatles").values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
El método values() admite argumentos posicionales opcionales, *fields, que especifican nombres de campo a los que el SELECT debe limitarse. Si especificas los campos, cada diccionario contendrá solo las claves y valores de los campos que especifiques. Si no especificas los campos, cada diccionario contendrá una clave y valor para cada campo en la tabla de base de datos.
Ejemplo:
>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values("id", "name")
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
El método values() también admite argumentos keyword opcionales, **expressions, que se pasan a annotate():
>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower("name"))
<QuerySet [{'lower_name': 'beatles blog'}]>
Puedes utilizar consultas de lookup integradas y consultas personalizadas en la ordenación. Por ejemplo:
>>> from django.db.models import CharField
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values("name__lower")
<QuerySet [{'name__lower': 'beatles blog'}]>
Un agregado dentro de una cláusula values() se aplica antes que otros argumentos dentro de la misma cláusula values(). Si necesitas agrupar por otro valor, agrega ese valor a una cláusula values() anterior en lugar de eso. Por ejemplo:
>>> from django.db.models import Count
>>> Blog.objects.values("entry__authors", entries=Count("entry"))
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>
>>> Blog.objects.values("entry__authors").annotate(entries=Count("entry"))
<QuerySet [{'entry__authors': 1, 'entries': 33}]>
Un par de sutilezas que vale la pena mencionar:
Si tienes un campo llamado foo que es un ForeignKey, el llamado por defecto a values() devolverá una clave de diccionario llamada foo_id, ya que este es el nombre del atributo oculto del modelo que almacena el valor real (el atributo foo se refiere al modelo relacionado). Cuando estás llamando a values() y pasando nombres de campos, puedes pasar foo o foo_id y obtendrás lo mismo (la clave de diccionario coincidirá con el nombre del campo que pasaste).
Ejemplo:
>>> Entry.objects.values()
<QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>
>>> Entry.objects.values("blog")
<QuerySet [{'blog': 1}, ...]>
>>> Entry.objects.values("blog_id")
<QuerySet [{'blog_id': 1}, ...]>
Cuando usas values() junto con distinct(), ten en cuenta que la ordenación puede afectar los resultados. Consulta la nota en distinct() para detalles.
Si utilizas una cláusula values() después de un llamado a extra(), cualquier campo definido por un argumento select en el extra() debe incluirse explícitamente en la cláusula values(). Cualquier llamado a extra() hecho después de una cláusula values() ignorará los campos seleccionados extra.
Llamar a only() y defer() después de values() no tiene sentido, por lo que hacerlo levantará un TypeError.
Combinar transformaciones y agregados requiere el uso de dos llamados a annotate(), ya sea explícitamente o como argumentos de palabra clave a values(). Como arriba, si la transformación ha sido registrada en el tipo de campo relevante se puede omitir el primer annotate(), por lo que los siguientes ejemplos son equivalentes:
>>> from django.db.models import CharField, Count
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values("entry__authors__name__lower").annotate(entries=Count("entry"))
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
>>> Blog.objects.values(entry__authors__name__lower=Lower("entry__authors__name")).annotate(
... entries=Count("entry")
... )
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
>>> Blog.objects.annotate(entry__authors__name__lower=Lower("entry__authors__name")).values(
... "entry__authors__name__lower"
... ).annotate(entries=Count("entry"))
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
Es útil cuando sabes que solo necesitarás valores de un pequeño número de campos disponibles y no necesitarás la funcionalidad de un objeto modelo. Es más eficiente seleccionar solo los campos que necesitas usar.
Finalmente, ten en cuenta que puedes llamar a filter(), order_by(), etc. después del llamado a values(), lo que significa que estas dos llamadas son idénticas:
Blog.objects.values().order_by("id")
Blog.objects.order_by("id").values()
Los textos traducidos son:
También puedes referirte a campos en modelos relacionados con relaciones inversas a través de los atributos OneToOneField, ForeignKey y ManyToManyField:
>>> Blog.objects.values("name", "entry__headline")
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>
Advertencia
Porque los atributos de las relaciones inversas y ManyToManyField pueden tener múltiples filas relacionadas, incluir estas puede tener un efecto multiplicador en el tamaño de tu conjunto de resultados. Esto se notará especialmente si incluyes varios campos así en tu consulta values(), en cuyo caso se devolverán todas las combinaciones posibles.
Valores especiales para JSONField en SQLite
Debido a la forma en que están implementados los funciones SQL JSON_EXTRACT y JSON_TYPE en SQLite, y falta del tipo de datos BOOLEAN, values() devolverá True, False y None en lugar de las cadenas "true", "false", y "null" para transformaciones de claves de campo JSONField.
La cláusula SELECT generada al utilizar values() se actualizó para respetar el orden de los campos especificados *fields y las expresiones **expressions.
values_list()¶Esto es similar a values() excepto que en lugar de devolver diccionarios, devuelve tuplas cuando se itera sobre ellas. Cada tupla contiene el valor del campo o expresión correspondiente pasado al llamado values_list() — así que el primer elemento es el primer campo, etc. Por ejemplo:
>>> Entry.objects.values_list("id", "headline")
<QuerySet [(1, 'First entry'), ...]>
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list("id", Lower("headline"))
<QuerySet [(1, 'first entry'), ...]>
Si solo pasas un campo, también puedes pasar el parámetro flat. Si True, esto significa que los resultados devueltos son valores individuales, en lugar de tuplas de 1 elemento. Un ejemplo debería hacer más claro la diferencia:
>>> Entry.objects.values_list("id").order_by("id")
<QuerySet[(1,), (2,), (3,), ...]>
>>> Entry.objects.values_list("id", flat=True).order_by("id")
<QuerySet [1, 2, 3, ...]>
Es un error pasar flat cuando hay más de un campo.
Puedes pasar named=True para obtener los resultados como un namedtuple():
>>> Entry.objects.values_list("id", "headline", named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>
El uso de una tupla nombrada puede hacer que el resultado sea más legible, a expensas de una pequeña penalización en rendimiento por transformar los resultados en una tupla nombrada.
Si no pasas ningún valor a values_list(), devolverá todos los campos del modelo, en el orden en que se declararon.
Una necesidad común es obtener un valor de campo específico de una instancia de modelo determinada. Para lograr esto, utiliza values_list() seguido de una llamada a get().
>>> Entry.objects.values_list("headline", flat=True).get(pk=1)
'First entry'
values() y values_list() son ambos destinados como optimizaciones para un caso de uso específico: recuperar un subconjunto de datos sin el overhead de crear una instancia de modelo. Esta metáfora se desmorona cuando se trata con relaciones muchos-a-muchos y otras relaciones multivaluadas (como la relación uno-a-muchos de una clave foránea inversa) porque la suposición del «objeto por fila» no es válida.
Por ejemplo, observe el comportamiento al consultar a través de un ManyToManyField:
>>> Author.objects.values_list("name", "entry__headline")
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
('George Orwell', 'Why Socialists Do Not Believe in Fun'),
('George Orwell', 'In Defence of English Cooking'),
('Don Quixote', None)]>
Los autores con múltiples entradas aparecen varias veces y los autores sin ninguna entrada tienen None para la cabecera de la entrada.
De manera similar, cuando se consulta una clave foránea inversa, None aparece para las entradas que no tienen ningún autor:
>>> Entry.objects.values_list("authors")
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>
Valores especiales para JSONField en SQLite
A causa de la forma en que están implementados los funciones SQL JSON_EXTRACT y JSON_TYPE en SQLite, y falta del tipo de datos BOOLEAN, values_list() devolverá True, False y None en lugar de las cadenas "true", "false", y "null" para transformaciones de claves de campo JSONField.
La cláusula SELECT generada al utilizar values_list() se actualizó para respetar el orden de los campos especificados en *fields.
dates()¶Devuelve un conjunto de consultas (QuerySet) que evalúa a una lista de objetos :class: datetime.date que representan todas las fechas disponibles de un tipo particular dentro del contenido del conjunto de consultas.
field debe ser el nombre de un campo DateField de tu modelo. kind debe ser "year", "month", "week", o "day". Cada objeto :class: datetime.date en la lista de resultados está «truncado» al tipo dado.
"year" devuelve una lista de todos los valores distintos de año para el campo.
"month" devuelve una lista de todos los valores distintos de año/mes para el campo.
"week" devuelve una lista de todos los valores distintos de año/semana para el campo. Todas las fechas serán un lunes.
"day" devuelve una lista de todos los valores distintos de año/mes/día para el campo.
order, que tiene como valor por defecto 'ASC', debe ser 'ASC' o 'DESC'. Esto especifica cómo ordenar los resultados.
Ejemplos:
>>> Entry.objects.dates("pub_date", "year")
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates("pub_date", "month")
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates("pub_date", "week")
[datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)]
>>> Entry.objects.dates("pub_date", "day")
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates("pub_date", "day", order="DESC")
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains="Lennon").dates("pub_date", "day")
[datetime.date(2005, 3, 20)]
datetimes()¶Devuelve un conjunto de consultas (QuerySet) que evalúa a una lista de objetos :class: datetime.datetime que representan todas las fechas disponibles de un tipo particular dentro del contenido del conjunto de consultas.
field_name debería ser el nombre de un campo DateTimeField de tu modelo.
kind debe ser "year", "month", "week", "day", "hour", "minute", o "second". Cada objeto datetime.datetime en la lista de resultados se «trunca» al tipo dado.
order, que tiene como valor por defecto 'ASC', debe ser 'ASC' o 'DESC'. Esto especifica cómo ordenar los resultados.
tzinfo define la zona horaria a la que los datetimes se convierten antes de truncarlos. De hecho, un datetime determinado tiene diferentes representaciones dependiendo de la zona horaria utilizada. Este parámetro debe ser un objeto datetime.tzinfo. Si es None, Django utiliza la zona horaria actual. No tiene efecto cuando USE_TZ es False.
Nota
Esta función realiza las conversiones de zona horaria directamente en la base de datos. Como consecuencia, tu base de datos debe poder interpretar el valor de tzinfo.tzname(None). Esto se traduce en los siguientes requisitos:
SQLite: no hay requisitos. Las conversiones se realizan en Python.
PostgreSQL: no hay requisitos (ver Time Zones).
Oracle: no hay requisitos (ver Choosing a Time Zone File).
MySQL: carga las tablas de zona horaria con mysql_tzinfo_to_sql.
none()¶Llamar a none() creará un conjunto de consultas que nunca devuelve objetos y ninguna consulta se ejecutará al acceder a los resultados. Un conjunto de consultas qs.none() es una instancia de EmptyQuerySet.
Ejemplos:
>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True
all()¶Devuelve una copia del conjunto de consultas actual (o subclase de QuerySet). Esto puede ser útil en situaciones donde se desee pasar un administrador de modelos o un QuerySet y hacer más filtrado sobre el resultado. Después de llamar a all() en cualquiera de los objetos, definitivamente tendrá un QuerySet para trabajar con.
Cuando un conjunto de consultas es evaluado, típicamente se almacenan sus resultados. Si la data en la base de datos podría haber cambiado desde que un conjunto de consultas fue evaluado, puede obtener resultados actualizados para la misma consulta llamando a all() sobre un conjunto de consultas previamente evaluado.
union()¶Utiliza el operador SQL UNION para combinar los resultados de dos o más conjuntos de consultas. Por ejemplo:
>>> qs1.union(qs2, qs3)
El operador UNION selecciona solo valores distintos por defecto. Para permitir valores duplicados, utilice la argumento all=True.
union(), intersection() y difference() devuelven instancias de modelo del tipo del primer conjunto de consultas incluso si los argumentos son conjuntos de consultas de otros modelos. Pasar diferentes modelos funciona siempre que la lista SELECT sea la misma en todos los conjuntos de consultas (al menos los tipos, los nombres no importan siempre y cuando los tipos estén en el mismo orden). En tales casos, debe utilizar los nombres de columna del primer conjunto de consultas en métodos de conjunto de consultas aplicados al conjunto de consultas resultante. Por ejemplo:
>>> qs1 = Author.objects.values_list("name")
>>> qs2 = Entry.objects.values_list("headline")
>>> qs1.union(qs2).order_by("name")
Además, solo se permiten LIMIT, OFFSET, COUNT(*), ORDER BY y especificar columnas (es decir, slicing, count(), exists(), order_by() y values()/values_list()) en el conjunto de consultas resultante. Además, las bases de datos imponen restricciones sobre qué operaciones se permiten en las consultas combinadas. Por ejemplo, la mayoría de las bases de datos no permiten LIMIT o OFFSET en las consultas combinadas.
intersection()¶Utiliza el operador SQL INTERSECT para devolver los elementos compartidos de dos o más conjuntos de consultas. Por ejemplo:
>>> qs1.intersection(qs2, qs3)
See unión() para algunas restricciones.
diferencia()¶Utiliza el operador EXCEPT de SQL para mantener solo los elementos presentes en la QuerySet pero no en alguna otra QuerySet. Por ejemplo:
>>> qs1.difference(qs2, qs3)
See unión() para algunas restricciones.
extra()¶A veces, la sintaxis de consulta de Django por sí sola no puede expresar fácilmente una cláusula WHERE compleja. Para estos casos de borde, Django proporciona el modificador de consulta QuerySet extra() — un ganchillo para inyectar cláusulas específicas en el SQL generado por un QuerySet.
Utiliza este método como último recurso
Esta es una antigua API que pretendemos deprecate en algún momento del futuro. Utilízala solo si no puedes expresar tu consulta utilizando otros métodos de queryset. Si necesitas utilizarla, por favor envía un ticket usando la palabra clave QuerySet.extra <https://code.djangoproject.com/query?status=assigned&status=new&keywords=~QuerySet.extra>`_ con tu caso de uso (por favor revisa la lista de tickets existentes antes) para que podamos mejorar la API del queryset y permitir eliminar extra(). Ya no estamos mejorando ni corrigiendo bugs para este método.
Por ejemplo, esta utilización de extra()
>>> qs.extra(
... select={"val": "select col from sometable where othercol = %s"},
... select_params=(someparam,),
... )
is equivalent to:
>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))
El main beneficio de utilizar RawSQL es que puedes establecer output_field si lo necesitas. El principal inconveniente es que si te refieres a algún alias de tabla del conjunto de resultados en la SQL cruda, entonces es posible que Django cambie ese alias (por ejemplo, cuando el conjunto de resultados se utiliza como subconsulta en otra consulta).
Advertencia
Debes ser muy cuidadoso cada vez que utilices extra(). Cada vez que lo hagas, debes escapar cualquier parámetro que el usuario pueda controlar utilizando params para protegerte contra ataques de inyección SQL.
También no debes citar los placeholders en la cadena SQL. Este ejemplo es vulnerable a ataques de inyección SQL debido a las comillas alrededor de %s:
SELECT col FROM sometable WHERE othercol = '%s' # unsafe!
Puede leer más sobre cómo funciona la protección contra inyecciones de SQL de Django: protección contra inyecciones de SQL.
Por definición, estas consultas adicionales pueden no ser portables a diferentes motores de base de datos (porque estás escribiendo código SQL explícitamente) y violan el principio DRY, por lo que debes evitarlas si es posible.
Especifica uno o más de params, select, where o tables. Ninguno de los argumentos es obligatorio, pero debes utilizar al menos uno de ellos.
select
El argumento select te permite poner campos adicionales en la cláusula SELECT. Debe ser un diccionario que mapee nombres de atributos a cláusulas SQL para calcular ese atributo.
Ejemplo:
Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"})
Como resultado, cada objeto Entry tendrá un atributo adicional, is_recent, un booleano que representa si la fecha de publicación del entry es mayor que enero 1, 2006.
Django inserta el fragmento SQL dado directamente en la cláusula SELECT, por lo que el SQL resultante del ejemplo anterior sería algo como:
SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
FROM blog_entry;
El siguiente ejemplo es más avanzado; hace una subconsulta para dar a cada objeto Blog un atributo entry_count, un recuento entero de objetos Entry asociados:
Blog.objects.extra(
select={
"entry_count": "SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id"
},
)
En este caso particular, estamos aprovechando el hecho de que la consulta ya contiene la tabla blog_blog en su cláusula FROM.
El SQL resultante del ejemplo anterior sería:
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
FROM blog_blog;
Ten en cuenta que las paréntesis requeridos por la mayoría de los motores de base de datos alrededor de subconsultas no son necesarios en las cláusulas select de Django.
En algunos casos raros, es posible que desee pasar parámetros a las fracciones SQL en extra(select=...). Para este propósito, utilice el parámetro select_params.
Esto funcionará, por ejemplo:
Blog.objects.extra(
select={"a": "%s", "b": "%s"},
select_params=("one", "two"),
)
Si necesita utilizar una literal %s dentro de su cadena select, utilice la secuencia %%s.
where / tables
Puede definir cláusulas SQL WHERE explícitas — quizás para realizar no-joins explícitos — utilizando where. Puede agregar manualmente tablas a la cláusula SQL FROM utilizando tables.
Ambas where y tables aceptan una lista de cadenas. Todos los parámetros where se «AND»ean con cualquier otro criterio de búsqueda.
Ejemplo:
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
…translates (roughly) into the following SQL:
SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
Cuando utilices el parámetro tables, ten cuidado si estás especificando tablas que ya se utilizan en la consulta. Cuando agregas tablas adicionales mediante el parámetro tables, Django asume que deseas incluir esa tabla una vez más, si ya está incluida. Eso crea un problema, ya que el nombre de la tabla recibirá entonces un alias. Si una tabla aparece varias veces en una sentencia SQL, las segundas y posteriores apariciones deben utilizar aliases para que la base de datos pueda distinguirlas. Si estás haciendo referencia a la tabla adicional que agregaste en el parámetro where extra, esto va a causar errores.
Normalmente solo agregarás tablas adicionales que no ya aparecen en la consulta. Sin embargo, si ocurre el caso descrito anteriormente, hay algunas soluciones. Primero, ve si puedes evitar incluir la tabla adicional y utilizar la que ya está en la consulta. Si eso no es posible, coloca tu llamada a extra() al principio de la construcción del conjunto de resultados para que tu tabla sea el primer uso de esa tabla. Finalmente, si todo lo demás falla, mira la consulta producida y reescribe tu adición where para utilizar el alias dado a tu tabla adicional. El alias será el mismo cada vez que construyas el conjunto de resultados de la misma manera, por lo que puedes confiar en el nombre del alias para no cambiar.
order_by
Si necesitas ordenar el conjunto de resultados resultante utilizando algunos de los nuevos campos o tablas que has incluido mediante extra() utiliza el parámetro order_by de extra() y pasa una secuencia de cadenas. Estas cadenas deben ser campos del modelo (como en el método normal order_by() sobre conjuntos de resultados), de la forma table_name.column_name o un alias para una columna que especificaste en el parámetro select a extra().
Por ejemplo:
q = Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"})
q = q.extra(order_by=["-is_recent"])
Esto ordenaría todos los elementos para los cuales is_recent es verdadero al principio del conjunto de resultados (True se ordena antes de False en un orden descendente).
Esto muestra, por cierto, que puedes hacer múltiples llamadas a extra() y comportarse como esperas (agregando nuevas restricciones cada vez).
params
El parámetro where descrito anteriormente puede utilizar placeholders de cadena de base de datos estándar de Python — '%s' para indicar parámetros que el motor de la base de datos debe citar automáticamente. El argumento params es una lista de cualquier otro parámetro adicional a ser sustituido.
Ejemplo:
Entry.objects.extra(where=["headline=%s"], params=["Lennon"])
Siempre utiliza params en lugar de insertar valores directamente en where porque params asegurará que los valores se citen correctamente según tu backend particular. Por ejemplo, las comillas se escaparán correctamente.
Bad:
Entry.objects.extra(where=["headline='Lennon'"])
Buena
Entry.objects.extra(where=["headline=%s"], params=["Lennon"])
Advertencia
Si estás realizando consultas en MySQL, ten en cuenta que la coerción silenciosa de tipos de MySQL puede causar resultados inesperados al mezclar tipos. Si consultas sobre una columna de tipo cadena, pero con un valor entero, MySQL convertirá los tipos de todos los valores de la tabla a entero antes de realizar la comparación. Por ejemplo, si tu tabla contiene los valores 'abc' y 'def' y realizas la consulta WHERE mycolumn=0, ambas filas coincidirán. Para evitar esto, realiza el casting correcto antes de utilizar el valor en una consulta.
En algunas situaciones de modelado de datos complejas, tus modelos pueden contener muchos campos, algunos de los cuales podrían contener una gran cantidad de datos (por ejemplo, campos de texto), o requerir un procesamiento costoso para convertirlos en objetos Python. Si estás utilizando los resultados de una consulta de conjunto en alguna situación en la que no sepas si necesitas esos campos particulares cuando inicialmente se recupere la data, puedes decir a Django que no los recupere desde la base de datos.
Esta es realizada pasando los nombres de los campos a no cargar a defer().
Entry.objects.defer("headline", "body")
Un conjunto de consultas que tenga campos diferidos aún devolverá instancias del modelo. Cada campo diferido se recuperará desde la base de datos si accedes a ese campo (uno a la vez, no todos los campos diferidos al mismo tiempo).
Nota
Los campos diferidos no se cargarán de manera relajada como esto desde el código asíncrono. En su lugar, obtendrás una excepción SynchronousOnlyOperation. Si estás escribiendo código asíncrono, no debes intentar acceder a ningún campo que hayas defer().
Puedes realizar múltiples llamadas a defer(). Cada llamada agrega nuevos campos al conjunto diferido:
# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")
La orden en la que se agregan los campos al conjunto diferido no importa. Llamar a defer() con el nombre de un campo que ya ha sido diferido es inocuo (el campo seguirá siendo diferido).
Puedes posponer la carga de campos en modelos relacionados (si los modelos relacionados están cargando mediante select_related()) utilizando la notación estándar con doble guión bajo para separar campos relacionados:
Blog.objects.select_related().defer("entry__headline", "entry__body")
Si deseas eliminar el conjunto de campos diferidos, pasa None como parámetro a defer():
# Load all fields immediately.
my_queryset.defer(None)
Algunos campos en un modelo no se diferirán, incluso si los solicitas. Nunca puedes diferir la carga del campo principal. Si estás utilizando select_related() para recuperar modelos relacionados, no debes diferir la carga del campo que conecta desde el modelo principal a uno relacionado, lo que dará como resultado un error.
De manera similar, llamar a defer() (o su contraparte only()) incluyendo un argumento de una agregación (por ejemplo, utilizando el resultado de annotate()) no tiene sentido: hacerlo dará como resultado una excepción. Los valores agrupados siempre se cargarán en la queryset resultante.
Nota
El método defer() (y su primo, only(), a continuación) solo están disponibles para casos de uso avanzados. Proporcionan una optimización cuando has analizado tus consultas cuidadosamente y comprendes exactamente qué información necesitas y has medido que la diferencia entre devolver los campos que necesitas y el conjunto completo de campos del modelo será significativa.
Incluso si crees que estás en una situación de caso de uso avanzado, solo utiliza defer() cuando no puedas determinar al cargar la queryset si necesitarás los campos adicionales o no. Si frecuentemente cargas y utilizas un subconjunto particular de tus datos, la mejor elección que puedes hacer es normalizar tus modelos y poner los datos no cargados en un modelo separado (y tabla de base de datos). Si las columnas deben permanecer en una sola tabla por alguna razón, crea un modelo con Meta.managed = False (ver la documentación del atributo managed) que contenga solo los campos que normalmente necesitas cargar y utilizar ese donde podrías llamar a defer(). Esto hace que tu código sea más explícito para el lector, es ligeramente más rápido y consume un poco menos memoria en el proceso de Python.
Por ejemplo, ambos modelos utilizan la misma tabla de base de datos subyacente:
class CommonlyUsedModel(models.Model):
f1 = models.CharField(max_length=10)
class Meta:
managed = False
db_table = "app_largetable"
class ManagedModel(models.Model):
f1 = models.CharField(max_length=10)
f2 = models.CharField(max_length=10)
class Meta:
db_table = "app_largetable"
# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.defer("f2")
Si muchos campos necesitan ser duplicados en el modelo no administrado, puede ser mejor crear un modelo abstracto con los campos compartidos y luego tener que los modelos no administrados e administrados hereden del modelo abstracto.
only()¶El método only() esencialmente es lo contrario que defer(). Solo se cargarán los campos pasados a este método y que no están ya especificados como diferidos inmediatamente cuando la queryset se evalúa.
Si tienes un modelo donde casi todos los campos necesitan ser diferidos, utilizar only() para especificar el conjunto complementario de campos puede resultar en código más simple.
Supongamos que tienes un modelo con campos name, age y biography. Los siguientes dos conjuntos de consultas son los mismos, en términos de campos diferidos:
Person.objects.defer("age", "biography")
Person.objects.only("name")
Cada vez que llames a only() sustituye el conjunto de campos para cargar inmediatamente. El nombre del método es mnemónico: solo se cargan aquellos campos inmediatamente; el resto son diferidos. Por lo tanto, las llamadas sucesivas a only() resultan en que solo los campos finales sean considerados:
# This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")
Dado que defer() actúa incrementalmente (añadiendo campos al conjunto de campos diferidos), puedes combinar llamadas a only() y defer() y las cosas funcionarán lógicamente:
# Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")
# Final result loads headline immediately.
Entry.objects.defer("body").only("headline", "body")
Todas las precauciones en la nota para la documentación de defer() se aplican también a only(). Utilízalo con cautela y solo después de agotar tus otras opciones.
Utilizar only() y omitir un campo solicitado utilizando select_related() es un error, por otro lado, invocar only() sin argumentos, devolverá todos los campos (incluyendo anotaciones) cargados por el conjunto de consultas.
Al igual que con defer(), no puedes acceder a los campos no cargados desde código asíncrono y esperar que se carguen. En su lugar, obtendrás una excepción SynchronousOnlyOperation. Asegúrate de que todos los campos que puedas acceder estén en tu llamada a only().
using()¶Este método es para controlar qué base de datos utilizará el conjunto de consultas si estás utilizando más de una base de datos. El único argumento que toma este método es el alias de la base de datos, tal como se define en DATABASES.
Ejemplo:
# queries the database with the 'default' alias.
>>> Entry.objects.all()
# queries the database with the 'backup' alias
>>> Entry.objects.using("backup")
select_for_update()¶Devuelve un conjunto de consultas que bloquearán las filas hasta el final de la transacción, generando una sentencia SQL SELECT ... FOR UPDATE en bases de datos compatibles.
Por ejemplo:
from django.db import transaction
entries = Entry.objects.select_for_update().filter(author=request.user)
with transaction.atomic():
for entry in entries:
...
Cuando se evalúa el conjunto de consultas (por ejemplo, for entry in entries), todas las entradas coincidentes se bloquearán hasta el final del bloque de transacción, lo que significa que otras transacciones serán previstas para cambiar o adquirir bloques en ellas.
Normalmente, si otra transacción ha adquirido ya un bloqueo en una de las filas seleccionadas, la consulta se bloqueará hasta que el bloqueo sea liberado. Si este no es el comportamiento deseado, llama a select_for_update(nowait=True). Esto hará que la llamada no bloquee. Si se ha adquirido un bloqueo en conflicto por otra transacción, se levantará DatabaseError cuando se evalúe el conjunto de consultas. También puedes ignorar las filas bloqueadas utilizando select_for_update(skip_locked=True) en lugar de eso. Los parámetros nowait y skip_locked son mutuamente excluyentes y cualquier intento de llamar a select_for_update() con ambos parámetros habilitados dará como resultado un ValueError.
Por defecto, select_for_update() bloquea todas las filas que se seleccionan por la consulta. Por ejemplo, las filas de objetos relacionados especificados en select_related() se bloquearán además de las filas del modelo del conjunto de consultas. Si no es lo deseado, especifique los objetos relacionados que quieres bloquear en select_for_update(of=(...)) utilizando la misma sintaxis de campos como select_related(). Utiliza el valor 'self' para referirte al modelo del conjunto de consultas.
Bloquear modelos padre en select_for_update(of=(...))
Si deseas bloquear modelos padre cuando se utiliza herencia múltiple, debes especificar campos de enlace de los padres (por defecto <nombre_modelo_padre>_ptr) en el argumento of. Por ejemplo:
Restaurant.objects.select_for_update(of=("self", "place_ptr"))
Utilizando select_for_update(of=(...)) con campos especificados
Si deseas bloquear modelos y especificar campos seleccionados, por ejemplo utilizando values(), debes seleccionar al menos un campo de cada modelo en el argumento of. Los modelos sin campos seleccionados no se bloquearán.
Solo en PostgreSQL, puedes pasar no_key=True para adquirir un bloqueo más débil que aún permite crear filas que simplemente refieren las filas bloqueadas (a través de una clave foránea, por ejemplo) mientras el bloqueo está en lugar. La documentación de PostgreSQL tiene más detalles sobre modos de bloqueo a nivel de fila.
You no puedes utilizar select_for_update() en relaciones nulas:
>>> Person.objects.select_related("hometown").select_for_update()
Traceback (most recent call last):
...
django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join
Para evitar esa restricción, puedes excluir objetos nulos si no te importa:
>>> Person.objects.select_related("hometown").select_for_update().exclude(hometown=None)
<QuerySet [<Person: ...)>, ...]>
Los backends de bases de datos postgresql, oracle y mysql soportan select_for_update(). Sin embargo, MariaDB solo soporta el argumento nowait, MariaDB 10.6+ también soporta el argumento skip_locked y MySQL soporta los argumentos nowait, skip_locked y of. El argumento no_key solo se soporta en PostgreSQL.
Al pasar nowait=True, skip_locked=True, no_key=True o of a select_for_update() utilizando backends de bases de datos que no soportan estas opciones, como MySQL, se levanta un error NotSupportedError. Esto previene el código de bloquear inesperadamente.
Evaluar una consulta con select_for_update() en modo autocommit en backends que soporten SELECT ... FOR UPDATE es un error TransactionManagementError porque las filas no se bloquean en ese caso. Si se permite, esto facilitaría la corrupción de datos y podría fácilmente ser causado por código que llama a que espera ejecutarse dentro de una transacción fuera de ella.
Utilizar select_for_update() en backends que no soporten SELECT ... FOR UPDATE (como SQLite) no tendrá efecto. SELECT ... FOR UPDATE no se agregará a la consulta y no se levantará un error si select_for_update() se utiliza en modo autocommit.
Advertencia
Aunque select_for_update() normalmente falla en modo autocommit, ya que TestCase envuelve automáticamente cada prueba en una transacción, llamar a select_for_update() en un TestCase incluso fuera de un bloque atomic() (quizás inesperadamente) pasará sin levantar un error TransactionManagementError. Para probar correctamente select_for_update() debes utilizar TransactionTestCase.
Ciertas expresiones pueden no estar soportadas
PostgreSQL no soporta select_for_update() con expresiones Window.
Toma una consulta SQL cruda, la ejecuta y devuelve un objeto de tipo django.db.models.query.RawQuerySet. Esta instancia de RawQuerySet puede ser iterada exactamente igual que un conjunto normal de consultas para proporcionar instancias de objetos.
Consulte la documentación sobre Ejecutando consultas SQL crudas para obtener más información.
Advertencia
La función raw() siempre desencadena una nueva consulta y no tiene en cuenta las filtraciones previas. Por lo tanto, debe ser llamada generalmente desde el Manager o desde una instancia de QuerySet fresca.
Deben utilizarse conjuntos de consultas combinados con el mismo modelo.
&)¶Combina dos conjuntos de consultas utilizando el operador SQL AND de manera similar a la concatenación de filtros.
Los siguientes son equivalentes:
Model.objects.filter(x=1) & Model.objects.filter(y=2)
Model.objects.filter(x=1).filter(y=2)
Equivalente en SQL:
SELECT ... WHERE x=1 AND y=2
|)¶Combina dos conjuntos de consultas (QuerySet) utilizando el operador SQL OR.
Los siguientes son equivalentes:
Model.objects.filter(x=1) | Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) | Q(y=2))
Equivalente en SQL:
SELECT ... WHERE x=1 OR y=2
El carácter | no es una operación comutativa, ya que pueden generarse consultas equivalentes pero diferentes.
Combina dos conjuntos de consultas (QuerySet) utilizando el operador SQL XOR. Una expresión XOR coincide con las filas que coinciden con un número impar de operandos.
Los siguientes son equivalentes:
Model.objects.filter(x=1) ^ Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) ^ Q(y=2))
Equivalente en SQL:
SELECT ... WHERE x=1 XOR y=2
Nota
XOR se admite nativamente en MariaDB y MySQL. En otras bases de datos, x ^ y ^ ... ^ z se convierte en una equivalente:
(x OR y OR ... OR z) AND
1=MOD(
(CASE WHEN x THEN 1 ELSE 0 END) +
(CASE WHEN y THEN 1 ELSE 0 END) +
...
(CASE WHEN z THEN 1 ELSE 0 END),
2
)
Los siguientes métodos del conjunto de consultas evalúan el conjunto de consultas y devuelven algo distinto a un conjunto de consultas.
Estos métodos no utilizan una caché (consulte Caché y QuerySet). En su lugar, consultan la base de datos cada vez que se llaman.
Dado que estos métodos evalúan el conjunto de consultas, son llamadas bloqueantes y por lo tanto sus versiones principales (sincrónicas) no pueden ser llamadas desde código asíncrono. Por esta razón, cada uno tiene una versión correspondiente asíncrona con un prefijo a - por ejemplo, en lugar de get(…) puedes utilizar await aget(…).
En general, no hay diferencia en el comportamiento aparte de su naturaleza asíncrona, pero cualquier diferencia se indica a continuación junto a cada método.
get()¶Versión asíncrona: aget()
Devuelve el objeto que coincide con los parámetros de búsqueda proporcionados, que deben estar en el formato descrito en Búsquedas de campo. Debes utilizar búsquedas garantizadas como única, como la clave primaria o campos en una restricción única. Por ejemplo:
Entry.objects.get(id=1)
Entry.objects.get(Q(blog=blog) & Q(entry_number=1))
Si esperas que un conjunto de resultados ya devuelva una fila, puedes usar get() sin argumentos para devolver el objeto correspondiente a esa fila:
Entry.objects.filter(pk=1).get()
Si get() no encuentra ningún objeto, lanza una excepción Model.DoesNotExist
Entry.objects.get(id=-999) # raises Entry.DoesNotExist
Si get() encuentra más de un objeto, lanza una excepción Model.MultipleObjectsReturned
Entry.objects.get(name="A Duplicated Name") # raises Entry.MultipleObjectsReturned
Ambas clases de excepciones son atributos de la clase del modelo y específicas de ese modelo. Si deseas manejar excepciones de este tipo desde varios llamados a get() para diferentes modelos, puedes utilizar sus clases base generales. Por ejemplo, puedes usar django.core.exceptions.ObjectDoesNotExist para manejar excepciones DoesNotExist desde múltiples modelos:
from django.core.exceptions import ObjectDoesNotExist
try:
blog = Blog.objects.get(id=1)
entry = Entry.objects.get(blog=blog, entry_number=1)
except ObjectDoesNotExist:
print("Either the blog or entry doesn't exist.")
create()¶Versión asíncrona: acreate()
Un método conveniente para crear un objeto y guardar todo en una sola paso. Por lo tanto:
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
No hay nada que traducir, solo la palabra «and».
p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)
son equivalentes.
El texto traducido es el siguiente:
get_or_create()¶Versión asíncrona: aget_or_create()
Un método de conveniencia para buscar un objeto con los parámetros dados kwargs (puede estar vacío si tu modelo tiene valores por defecto para todos los campos), creando uno si es necesario.
Devuelve una tupla de (object, created), donde object es el objeto recuperado o creado y created es un booleano que especifica si se creó un nuevo objeto.
Esto está diseñado para prevenir la creación de objetos duplicados cuando se hacen solicitudes en paralelo, y como atajo a código boilerplatish. Por ejemplo:
try:
obj = Person.objects.get(first_name="John", last_name="Lennon")
except Person.DoesNotExist:
obj = Person(first_name="John", last_name="Lennon", birthday=date(1940, 10, 9))
obj.save()
Aquí, con solicitudes concurrentes, pueden hacerse múltiples intentos de guardar un Person con los mismos parámetros. Para evitar esta condición de carrera, el ejemplo anterior se puede reescribir utilizando get_or_create() como se muestra a continuación:
obj, created = Person.objects.get_or_create(
first_name="John",
last_name="Lennon",
defaults={"birthday": date(1940, 10, 9)},
)
Cualquier argumento clave pasado a get_or_create() — excepto uno opcional llamado defaults — se utilizará en una get() llamada. Si se encuentra un objeto, get_or_create() devuelve una tupla de ese objeto y False.
Advertencia
Este método es atómico suponiendo que la base de datos impone la unicidad de los argumentos clave (ver unique o unique_together). Si los campos utilizados en los argumentos clave no tienen una restricción de unicidad, las llamadas concurrentes a este método pueden resultar en múltiples filas con los mismos parámetros siendo insertadas.
Puedes especificar condiciones más complejas para el objeto recuperado al encadenar get_or_create() con filter() y utilizando objetos Q. Por ejemplo, para recuperar a Robert o Bob Marley si cualquiera de ellos existe, y crear el último en caso contrario:
from django.db.models import Q
obj, created = Person.objects.filter(
Q(first_name="Bob") | Q(first_name="Robert"),
).get_or_create(last_name="Marley", defaults={"first_name": "Bob"})
Si se encuentran múltiples objetos, get_or_create() levanta la excepción MultipleObjectsReturned. Si un objeto no está encontrado, get_or_create() instanciará y guardará un nuevo objeto, devolviendo una tupla del nuevo objeto y True. El nuevo objeto se creará aproximadamente según este algoritmo:
params = {k: v for k, v in kwargs.items() if "__" not in k}
params.update({k: v() if callable(v) else v for k, v in defaults.items()})
obj = self.model(**params)
obj.save()
Si en inglés significa comenzar con cualquier argumento de palabra clave no 'defaults' que no contenga un doble subrayado (lo que indicaría una búsqueda no exacta). Luego, agrega el contenido de defaults, sobreescribiendo cualquier clave si es necesario, y utiliza el resultado como los argumentos de palabra clave para la clase del modelo. Si hay llamables en defaults, evalúalos. Como se sugiere arriba, esto es una simplificación del algoritmo que se usa, pero contiene todos los detalles pertinentes. La implementación interna tiene algunas comprobaciones de errores adicionales y maneja algunas condiciones de borde extra; si estás interesado, lee el código.
Si tienes un campo llamado defaults y deseas utilizarlo como una búsqueda exacta en get_or_create(), utiliza 'defaults__exact', como se muestra a continuación:
Foo.objects.get_or_create(defaults__exact="bar", defaults={"defaults": "baz"})
El método get_or_create() tiene comportamiento de error similar a create() cuando estás utilizando claves primarias especificadas manualmente. Si un objeto necesita ser creado y la clave ya existe en la base de datos, se levantará una excepción IntegrityError.
Finalmente, una palabra sobre el uso de get_or_create() en vistas Django. Asegúrate de utilizarlo solo en solicitudes POST a menos que tengas una buena razón para no hacerlo. Las solicitudes GET no deberían tener ningún efecto en los datos. En su lugar, utiliza POST siempre que una solicitud a una página tenga un efecto lateral en tus datos. Para más información, consulta Métodos seguros en la especificación HTTP.
Advertencia
Puedes utilizar get_or_create() a través de atributos de relaciones inversas y ManyToManyField. En ese caso, restringirás las consultas dentro del contexto de esa relación. Esto podría llevar a problemas de integridad si no lo utilizas consistentemente.
Si los siguientes modelos:
class Chapter(models.Model):
title = models.CharField(max_length=255, unique=True)
class Book(models.Model):
title = models.CharField(max_length=256)
chapters = models.ManyToManyField(Chapter)
Puedes utilizar get_or_create() a través del campo chapters de Book, pero solo busca dentro del contexto de ese libro:
>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError
Esto está sucediendo porque está tratando de obtener o crear «Capítulo 1» a través del libro «Ulysses», pero no puede hacerlo: la relación no puede buscar ese capítulo porque no está relacionado con ese libro, pero tampoco puede crearlo porque el campo title debe ser único.
update_or_create()¶Versión asíncrona: aupdate_or_create()
Método conveniente para actualizar un objeto con los parámetros dados en kwargs, creando uno nuevo si es necesario. Ambos create_defaults y defaults son diccionarios de pares (campo, valor). Los valores en ambos create_defaults y defaults pueden ser llamables. defaults se utiliza para actualizar el objeto mientras que create_defaults se utilizan para la operación de creación. Si no se proporciona create_defaults, defaults se utilizará para la operación de creación.
Devuelve una tupla de (object, created), donde object es el objeto creado o actualizado y created es un booleano que especifica si se creó un nuevo objeto.
El método update_or_create intenta recuperar un objeto desde la base de datos según los parámetros dados en kwargs. Si se encuentra una coincidencia, actualiza los campos pasados en el diccionario defaults.
Esto es pensado como un atajo para código boilerplatish. Por ejemplo:
defaults = {"first_name": "Bob"}
create_defaults = {"first_name": "Bob", "birthday": date(1940, 10, 9)}
try:
obj = Person.objects.get(first_name="John", last_name="Lennon")
for key, value in defaults.items():
setattr(obj, key, value)
obj.save()
except Person.DoesNotExist:
new_values = {"first_name": "John", "last_name": "Lennon"}
new_values.update(create_defaults)
obj = Person(**new_values)
obj.save()
Este patrón se vuelve bastante inmanejable a medida que aumenta el número de campos en un modelo. El ejemplo anterior se puede reescribir utilizando update_or_create() de la siguiente manera:
obj, created = Person.objects.update_or_create(
first_name="John",
last_name="Lennon",
defaults={"first_name": "Bob"},
create_defaults={"first_name": "Bob", "birthday": date(1940, 10, 9)},
)
Para una descripción detallada de cómo se resuelven los nombres pasados en kwargs, consulte get_or_create().
Como se describe arriba en get_or_create(), este método es propenso a un problema de condición de carrera que puede resultar en la inserción simultánea de múltiples filas si no se garantiza la unicidad a nivel de base de datos.
Al igual que get_or_create() y create(), si se utilizan claves primarias especificadas manualmente y un objeto necesita ser creado pero la clave ya existe en la base de datos, se levanta una IntegrityError.
bulk_create()¶Versión asíncrona: abulk_create()
Este método inserta la lista de objetos proporcionada en la base de datos de manera eficiente (generalmente solo 1 consulta, independientemente del número de objetos que hay), y devuelve los objetos creados como una lista, en el mismo orden en que se proporcionaron:
>>> objs = Entry.objects.bulk_create(
... [
... Entry(headline="This is a test"),
... Entry(headline="This is only a test"),
... ]
... )
Sin embargo, este método tiene un número de limitaciones:
El método save() del modelo no será llamado, y los señales pre_save y post_save no serán enviadas.
No funciona con modelos hijos en una escena de herencia múltiple de tablas.
Si el atributo primario del modelo es un AutoField y ignore_conflicts es falso, el atributo de clave primaria solo se puede recuperar en ciertas bases de datos (actualmente PostgreSQL, MariaDB y SQLite 3.35+). En otras bases de datos, no se establecerá.
No funciona con relaciones muchos-a-muchos.
Casta objs a una lista, lo que evalúa completamente objs si es un generador. La cast permite inspeccionar todos los objetos para que cualquier objeto con una clave primaria manualmente establecida se pueda insertar primero. Si deseas insertar objetos en lotes sin evaluar el generador completo de una sola vez, puedes utilizar esta técnica siempre y cuando los objetos no tengan ninguna clave primaria manualmente configurada:
from itertools import islice
batch_size = 100
objs = (Entry(headline="Test %s" % i) for i in range(1000))
while True:
batch = list(islice(objs, batch_size))
if not batch:
break
Entry.objects.bulk_create(batch, batch_size)
El parámetro batch_size controla cuántos objetos se crean en una sola consulta. El valor predeterminado es crear tantos objetos en un lote como permita la base de datos. (SQLite y Oracle limitan el número de parámetros en una consulta.)
En bases de datos que lo admiten (todas menos Oracle), establecer el parámetro ignore_conflicts en True le dice a la base de datos que ignore el fallo al insertar cualquier fila que falle las restricciones como valores únicos duplicados.
On bases de datos que lo soporten (todos excepto Oracle), establecer el parámetro update_conflicts en True, le dice a la base de datos que actualice update_fields cuando una inserción de fila falla debido a conflictos. En PostgreSQL y SQLite, además de update_fields, se debe proporcionar una lista de unique_fields que pueden estar en conflicto.
Habilitando el parámetro ignore_conflicts deshabilita la configuración de la clave primaria en cada instancia del modelo (si la base de datos lo soporta normalmente).
Advertencia
En MySQL y MariaDB, establecer el parámetro ignore_conflicts en True convierte ciertos tipos de errores, excepto los duplicados de clave, en advertencias. Incluso con Modo estricto. Por ejemplo: valores inválidos o violaciones de no nulidad. Consulte la documentación de MySQL y la documentación de MariaDB para obtener más detalles.
bulk_update()¶Versión asíncrona: abulk_update()
Este método actualiza eficientemente los campos dados en las instancias del modelo proporcionadas, generalmente con una sola consulta, y devuelve el número de objetos actualizados:
>>> objs = [
... Entry.objects.create(headline="Entry 1"),
... Entry.objects.create(headline="Entry 2"),
... ]
>>> objs[0].headline = "This is entry 1"
>>> objs[1].headline = "This is entry 2"
>>> Entry.objects.bulk_update(objs, ["headline"])
2
Se utiliza el método QuerySet.update() para guardar los cambios, por lo que es más eficiente que iterar a través de la lista de modelos y llamar a save() en cada uno de ellos, pero tiene algunas limitaciones:
No se puede actualizar la clave primaria del modelo.
No se llama al método save() de cada modelo y no se envían los señales pre_save y post_save.
Si se están actualizando un gran número de columnas en un gran número de filas, el SQL generado puede ser muy grande. Evite esto especificando una batch_size adecuada.
When actualizando un gran número de objetos, ten en cuenta que bulk_update() prepara todas las cláusulas WHEN para cada objeto en todos los lotes antes de ejecutar cualquier consulta. Esto puede requerir más memoria del esperado. Para reducir el uso de memoria, puedes utilizar una aproximación como esta:
from itertools import islice
batch_size = 100
ids_iter = range(1000)
while ids := list(islice(ids_iter, batch_size)):
batch = Entry.objects.filter(ids__in=ids)
for entry in batch:
entry.headline = f"Updated headline {entry.pk}"
Entry.objects.bulk_update(batch, ["headline"], batch_size=batch_size)
Actualizando campos definidos en ancestros de herencia multi-tabla provocará un extra query por cada ancestro.
Cuando un lote individual contiene duplicados, solo la primera instancia en ese lote dará lugar a una actualización.
El número de objetos actualizados devuelto por la función puede ser menor que el número de objetos pasados. Esto puede deberse a objetos duplicados pasados que se actualizan en el mismo lote o condiciones de carrera tales que los objetos ya no están presentes en la base de datos.
El parámetro batch_size controla cuántos objetos se guardan en una sola consulta. El valor por defecto es actualizar todos los objetos en un solo lote, excepto para SQLite y Oracle que tienen restricciones sobre el número de variables utilizadas en una consulta.
count()¶Versión asíncrona: acount()
Devuelve un entero que representa el número de objetos en la base de datos que coinciden con el QuerySet.
Ejemplo:
# Returns the total number of entries in the database.
Entry.objects.count()
# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains="Lennon").count()
Una llamada a count() realiza una consulta SELECT COUNT(*) detrás de escena, por lo que siempre debes utilizar count() en lugar de cargar todos los registros en objetos Python y llamar a len() en el resultado (a menos que necesites cargar los objetos en memoria de cualquier manera, en cuyo caso len() será más rápido).
Ten en cuenta que si deseas obtener el número de elementos en un QuerySet y también estás recuperando instancias del modelo desde él (por ejemplo, iterando sobre él), probablemente sea más eficiente utilizar len(queryset) lo que no causará una consulta extra a la base de datos como sí haría count().
Si el conjunto de resultados ya ha sido recuperado completamente, count() utilizará esa longitud en lugar de realizar una consulta adicional en la base de datos.
Versión asíncrona: ain_bulk()
Toma una lista de valores de campo ( id_list ) y el nombre del campo (field_name) para esos valores, y devuelve un diccionario que mapee cada valor a una instancia del objeto con el valor de campo dado. Nunca se levantarán excepciones django.core.exceptions.ObjectDoesNotExist por in_bulk; es decir, cualquier valor id_list no coincidente con ninguna instancia simplemente será ignorado. Si no se proporciona id_list, se devolverán todos los objetos en el conjunto de resultados. field_name debe ser un campo único o un campo distinto (si solo se especifica un campo en distinct()). field_name tiene como valor por defecto la clave primaria.
Ejemplo:
>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}
>>> Blog.objects.in_bulk()
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>}
>>> Blog.objects.in_bulk(["beatles_blog"], field_name="slug")
{'beatles_blog': <Blog: Beatles Blog>}
>>> Blog.objects.distinct("name").in_bulk(field_name="name")
{'Beatles Blog': <Blog: Beatles Blog>, 'Cheddar Talk': <Blog: Cheddar Talk>, 'Django Weblog': <Blog: Django Weblog>}
Si pasas a in_bulk() una lista vacía, obtendrás un diccionario vacío.
Versión asíncrona: aiterator()
Evaluates el conjunto de resultados (realizando la consulta) y devuelve un iterador (consultar PEP 234) sobre los resultados, o un iterador asíncrono (consultar PEP 492) si llamas a su versión asíncrona aiterator.
Un conjunto de resultados típicamente almacena sus resultados internamente para que las evaluaciones repetidas no resulten en consultas adicionales. En contraste, iterator() leerá los resultados directamente, sin hacer ningún almacenamiento en caché a nivel del conjunto de resultados (internamente, el iterador predeterminado llama a iterator() y almacena el valor de retorno). Para un conjunto de resultados que devuelve un gran número de objetos que solo se necesitan acceder una vez, esto puede resultar en mejores rendimientos y una reducción significativa en la memoria.
Nota que utilizar iterator() en un conjunto de resultados que ya ha sido evaluado obligará a evaluarlo nuevamente, repitiendo la consulta.
iterator() es compatible con llamadas anteriores a prefetch_related() siempre que se proporcione el valor de chunk_size. Valores más grandes requerirán menos consultas para lograr la prefetching, pero con un mayor uso de memoria.
En algunas bases de datos (por ejemplo, Oracle, SQLite), el número máximo de términos en una cláusula SQL IN puede estar limitado. Por lo tanto, se deben utilizar valores inferiores a este límite. (En particular, cuando se prefetcha a través de dos o más relaciones, debe haber un valor de chunk_size pequeño suficiente para que el número anticipado de resultados para cada relación prefijada aún caiga por debajo del límite.)
A medida que la consulta no prefija objetos relacionados, proporcionar ningún valor para chunk_size resultará en Django utilizar un valor predeterminado implícito de 2000.
Según el motor de base de datos, los resultados de la consulta se cargarán todo a la vez o se transmitirán desde la base de datos utilizando cursor del lado del servidor.
Oracle y PostgreSQL utilizan cursor del lado del servidor para transmitir resultados desde la base de datos sin cargar el conjunto de resultados completo en memoria.
El controlador de Oracle siempre utiliza cursor del lado del servidor.
Con cursor del lado del servidor, el parámetro chunk_size especifica el número de resultados que se almacenan a nivel del controlador de la base de datos. Recuperar trozos más grandes disminuye el número de vueltas entre el controlador de la base de datos y la base de datos, pero con un mayor uso de memoria.
En PostgreSQL, los cursor del lado del servidor solo se utilizarán cuando la configuración DISABLE_SERVER_SIDE_CURSORS sea False. Lee Transaction pooling and server-side cursors si estás utilizando un controlador de conexiones configurado en modo de agrupación de transacciones. Cuando los cursor del lado del servidor están deshabilitados, el comportamiento es el mismo que para las bases de datos que no admiten cursor del lado del servidor.
MySQL no soporta resultados en streaming, por lo que el motor de bases de datos de Python carga el conjunto completo de resultados en memoria. El conjunto de resultados se transforma luego en objetos de fila de Python mediante el método fetchmany() definido en PEP 249.
SQLite puede obtener resultados en lotes utilizando fetchmany(), pero ya que SQLite no proporciona aislamiento entre consultas dentro de una conexión, ten cuidado al escribir en la tabla que se está iterando. Consulte Aislamiento al utilizar QuerySet.iterator() para más información.
El parámetro chunk_size controla el tamaño de los lotes que Django recupera del motor de bases de datos. Los lotes más grandes disminuyen la sobrecarga de comunicación con el motor de bases de datos a expensas de un ligero aumento en consumo de memoria.
Tan pronto como el conjunto de consultas no prefija objetos relacionados, proporcionar ningún valor para chunk_size resultará en que Django utilice un valor implícito por defecto de 2000, un valor derivado de una calculación en la lista de correo del psycopg:
Asumiendo filas de 10-20 columnas con una mezcla de datos textuales y numéricos, 2000 va a obtener menos de 100KB de datos, lo que parece un buen compromiso entre el número de filas transferidas y los datos descartados si se sale del bucle temprano.
latest()¶Versión asíncrona: alatest()
Devuelve el objeto más reciente en la tabla según el campo(s) dado(s).
Este ejemplo devuelve el Entry más reciente en la tabla, según el campo pub_date:
Entry.objects.latest("pub_date")
También puedes elegir el más reciente basado en varios campos. Por ejemplo, para seleccionar el Entry con la fecha de caducidad más temprana cuando dos entradas tienen la misma fecha de publicación:
Entry.objects.latest("pub_date", "-expire_date")
El texto traducido es el siguiente:
Si la clase Meta de tu modelo especifica get_latest_by, puedes omitir cualquier argumento a earliest() o latest(). Los campos especificados en get_latest_by se utilizarán por defecto.
Como get(), earliest() y latest() levantan DoesNotExist` si no hay un objeto con los parámetros dados.
Ten en cuenta que earliest() y latest() existen puramente por conveniencia y legibilidad.
earliest() y latest() pueden devolver instancias con fechas nulas.
Dado que el ordenamiento se delega en la base de datos, los resultados en campos que permiten valores nulos pueden estar ordenados de manera diferente si utilizas diferentes bases de datos. Por ejemplo, PostgreSQL y MySQL ordenan los valores nulos como si fueran mayores que los no nulos, mientras que SQLite hace lo contrario.
Puede que desee filtrar los valores nulos:
Entry.objects.filter(pub_date__isnull=False).latest("pub_date")
earliest()¶Versión asíncrona: aearliest()
Funciona de manera similar a latest() excepto que el sentido se cambia.
first()¶Versión asíncrona: afirst()
Devuelve el primer objeto coincidente con la consulta, o None si no hay ningún objeto que coincida. Si la consulta de conjunto no tiene definido un ordenamiento, entonces la consulta se ordena automáticamente por la clave primaria. Esto puede afectar los resultados de agregación tal como se describe en Interacción con order_by().
Ejemplo:
p = Article.objects.order_by("title", "pub_date").first()
Ten en cuenta que first() es un método conveniente, el siguiente ejemplo de código es equivalente al ejemplo anterior:
try:
p = Article.objects.order_by("title", "pub_date")[0]
except IndexError:
p = None
last()¶Versión asíncrona: alast()
Funciona como first(), pero devuelve el último objeto en la consulta.
aggregate()¶Versión asíncrona: aaggregate()
Devuelve un diccionario de valores agregados (promedios, sumas, etc.) calculados sobre la QuerySet. Cada argumento a aggregate() especifica un valor que se incluirá en el diccionario que se devuelve.
Los textos traducidos son:
Los argumentos de palabra clave especificados para los agregados utilizarán la palabra clave como nombre para la anotación. Los argumentos anónimos tendrán un nombre generado basado en el nombre de la función de agregado y el campo del modelo que se está agrupando. Los agregados complejos no pueden utilizar argumentos anónimos y deben especificar un argumento de palabra clave como alias.
Por ejemplo, cuando estás trabajando con entradas de blog, puede que desees saber el número de autores que han contribuido a las entradas de blog:
>>> from django.db.models import Count
>>> Blog.objects.aggregate(Count("entry__authors"))
{'entry__authors__count': 16}
Al utilizar un argumento de palabra clave para especificar la función de agregado, puedes controlar el nombre del valor de agregación que se devuelve:
>>> Blog.objects.aggregate(number_of_authors=Count("entry__authors"))
{'number_of_authors': 16}
Para una discusión en profundidad sobre la agregación, consulte la guía del tema sobre Agregación.
exists()¶Versión asíncrona: aexists()
Devuelve True si el conjunto de consultas QuerySet contiene algún resultado, y False si no. Este intenta realizar la consulta de la manera más simple y rápida posible, pero sí ejecuta casi la misma consulta que una normal QuerySet query.
exists() es útil para búsquedas relacionadas con la existencia de cualquier objeto en un conjunto de consultas QuerySet, particularmente en el contexto de un gran conjunto de consultas QuerySet.
Para encontrar si un conjunto de consultas contiene algún elemento:
if some_queryset.exists():
print("There is at least one object in some_queryset")
Lo que será más rápido que:
if some_queryset:
print("There is at least one object in some_queryset")
Pero no por un grado muy grande (por lo tanto necesitando una gran consulta de conjunto para ganancias de eficiencia).
Además, si un some_queryset aún no ha sido evaluado, pero sabes que lo será en algún momento, entonces usar some_queryset.exists() hará más trabajo en general (una consulta para la verificación de existencia más una extra para luego recuperar los resultados) que usar bool(some_queryset), que recupera los resultados y luego verifica si alguno se devolvió.
contains()¶Versión asíncrona: acontains()
Devuelve True si el QuerySet contiene obj, y False si no lo hace. Esto intenta realizar la consulta de manera más simple y rápida posible.
contains() es útil para verificar la pertenencia de un objeto a un QuerySet, particularmente en el contexto de un gran QuerySet.
Para comprobar si un conjunto de consultas contiene un elemento específico:
if some_queryset.contains(obj):
print("Entry contained in queryset")
Esto será más rápido que lo siguiente, que requiere evaluar e iterar a través del conjunto de consultas completo:
if obj in some_queryset:
print("Entry contained in queryset")
Como exists(), si some_queryset aún no ha sido evaluado, pero sabes que lo será en algún momento, entonces usar some_queryset.contains(obj) hará una consulta adicional de base de datos, generalmente resultando en rendimiento más lento en general.
update()¶Versión asíncrona: aupdate()
Ejecuta una consulta de actualización SQL para los campos especificados y devuelve el número de filas coincidentes (que puede no ser igual al número de filas actualizadas si algunas filas ya tienen el nuevo valor).
Por ejemplo, para desactivar los comentarios en todas las entradas de blog publicadas en 2010, podrías hacer esto:
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
(Se asume que tu modelo Entry tiene campos pub_date y comments_on.)
Puedes actualizar múltiples campos — no hay límite en el número de campos que puedas actualizar. Por ejemplo, aquí actualizamos los campos comments_on y headline:
>>> Entry.objects.filter(pub_date__year=2010).update(
... comments_on=False, headline="This is old"
... )
El método update() se aplica instantáneamente, y la única restricción sobre el conjunto de consultas (QuerySet) que se actualiza es que solo puede actualizar columnas en la tabla principal del modelo, no en modelos relacionados. No puedes hacer esto, por ejemplo:
>>> Entry.objects.update(blog__name="foo") # Won't work!
La filtración basada en campos relacionados sigue siendo posible:
>>> Entry.objects.filter(blog__id=1).update(comments_on=True)
No puedes llamar a update() sobre un QuerySet que ya ha tenido una sección extraída o ya no puede ser filtrado.
El método update() devuelve el número de filas afectadas:
>>> Entry.objects.filter(id=64).update(comments_on=True)
1
>>> Entry.objects.filter(slug="nonexistent-slug").update(comments_on=True)
0
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
132
Si solo estás actualizando un registro y no necesitas hacer nada con el objeto del modelo, la mejor forma eficiente es llamar a update(), en lugar de cargar el objeto del modelo en memoria. Por ejemplo, en lugar de hacer esto:
e = Entry.objects.get(id=10)
e.comments_on = False
e.save()
…haz esto:
Entry.objects.filter(id=10).update(comments_on=False)
Usando update() también se evita una condición de carrera en la que algo podría cambiar en tu base de datos en el breve período de tiempo entre cargar el objeto y llamar a save().
MySQL does not support self-select updates
En MySQL, QuerySet.update() puede ejecutar un SELECT seguido de un UPDATE en lugar de un solo UPDATE cuando se filtran tablas relacionadas, lo que puede introducir una condición de carrera si ocurren cambios concurrentes entre las consultas. Para asegurar la atomicidad, considera utilizar transacciones o evitar condiciones de filtro tales como en MySQL.
Finalmente, comprende que update() realiza una actualización en el nivel SQL y, por lo tanto, no llama a ningún método save() de tus modelos, ni emite los señales pre_save o post_save (que son consecuencia del llamado a la Model.save()). Si deseas actualizar un conjunto de registros para un modelo que tiene un método save() personalizado, itera sobre ellos y llama a save(), como se muestra a continuación:
for e in Entry.objects.filter(pub_date__year=2010):
e.comments_on = False
e.save()
La cadena de order_by() con update() está soportada solo en MariaDB y MySQL, y se ignora para bases de datos diferentes. Esto es útil para actualizar un campo único en el orden especificado sin conflictos. Por ejemplo:
Entry.objects.order_by("-number").update(number=F("number") + 1)
Nota
La cláusula order_by() será ignorada si contiene anotaciones, campos heredados o consultas que abarcan relaciones.
delete()¶Versión asíncrona: adelete()
Ejecuta una consulta SQL de eliminación en todas las filas del conjunto de consultas QuerySet y devuelve el número de objetos eliminados y un diccionario con el número de eliminaciones por tipo de objeto.
La traducción es:
Por ejemplo, para eliminar todas las entradas de un blog en particular:
>>> b = Blog.objects.get(pk=1)
# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
(4, {'blog.Entry': 2, 'blog.Entry_authors': 2})
De forma predeterminada, Django emula la restricción SQL ON DELETE CASCADE mediante su ForeignKey — es decir, cualquier objeto con claves foráneas que apunten a los objetos a eliminar se eliminarán junto con ellos. Por ejemplo:
>>> blogs = Blog.objects.all()
# This will delete all Blogs and all of their Entry objects.
>>> blogs.delete()
(5, {'blog.Blog': 1, 'blog.Entry': 2, 'blog.Entry_authors': 2})
Este comportamiento en cascada es personalizable a través del argumento on_delete de la clase ForeignKey.
El método delete() realiza una eliminación en lote y no llama a los métodos delete() de tus modelos. Sin embargo, emite los señales pre_delete y post_delete para todos los objetos eliminados (incluidas las eliminaciones en cascada).
Django necesita cargar los objetos en memoria para enviar señales y manejar cascadas. Sin embargo, si no hay cascadas ni señales, entonces Django puede tomar un camino rápido y eliminar objetos sin cargarlos en memoria. Para grandes eliminaciones esto puede resultar en una reducción significativa del uso de memoria. La cantidad de consultas ejecutadas también se puede reducir.
Las ForeignKeys que están configuradas con on_delete DO_NOTHING no impiden tomar el camino rápido en la eliminación.
Ten en cuenta que las consultas generadas durante la eliminación de objetos es un detalle de implementación sujeto a cambios.
as_manager()¶Método de clase que devuelve una instancia de Manager con una copia de los métodos del QuerySet. Consulta Crear un administrador con métodos de QuerySet para obtener más detalles.
Ten en cuenta que, a diferencia de las otras entradas en esta sección, esto no tiene un variante asíncrono ya que no ejecuta una consulta.
explain()¶Versión asíncrona: aexplain()
Devuelve una cadena con el plan de ejecución del conjunto de consultas, que detalla cómo la base de datos ejecutaría la consulta, incluyendo cualquier índice o unión que se utilizarían. Conocer estos detalles puede ayudarte a mejorar el rendimiento de consultas lentas.
Por ejemplo, cuando se utiliza PostgreSQL:
>>> print(Blog.objects.filter(title="My Blog").explain())
Seq Scan on blog (cost=0.00..35.50 rows=10 width=12)
Filter: (title = 'My Blog'::bpchar)
La salida difiere significativamente entre bases de datos.
explain() está soportado por todos los backends de base de datos integrados excepto Oracle porque una implementación allí no es directa.
El parámetro format cambia el formato de salida desde el predeterminado de la base de datos, que suele ser de tipo texto. PostgreSQL admite formatos 'TEXT', 'JSON', 'YAML' y 'XML'. MariaDB y MySQL admiten formatos 'TEXT' (también llamados 'TRADITIONAL') y 'JSON'. MySQL 8.0.16+ también admite un formato mejorado 'TREE', que es similar a la salida de texto de PostgreSQL y se utiliza por defecto si está soportado.
Algunas bases de datos aceptan banderas que pueden devolver más información sobre la consulta. Pasa estas banderas como argumentos clave. Por ejemplo, cuando se utiliza PostgreSQL:
>>> print(Blog.objects.filter(title="My Blog").explain(verbose=True, analyze=True))
Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
Output: id, title
Filter: (blog.title = 'My Blog'::bpchar)
Planning time: 0.064 ms
Execution time: 0.058 ms
En algunas bases de datos, las banderas pueden hacer que la consulta se ejecute lo que podría tener efectos adversos en tu base de datos. Por ejemplo, la bandera ANALYZE soportada por MariaDB, MySQL 8.0.18+ y PostgreSQL podría resultar en cambios de datos si hay trampas o si una función se llama, incluso para consultas SELECT.
Se agregó el soporte para la opción generic_plan en PostgreSQL 16+.
Soporte para las opciones memory y serialize en PostgreSQL 17+ se agregó.
Las consultas de campo son cómo especificar el contenido de una cláusula SQL WHERE. Se especifican como argumentos de palabra clave a los métodos del conjunto de consultas filter(), exclude() y get().
Para una introducción, véase la documentación sobre modelos y consultas de base de datos: models and database queries documentation.
Las consultas de campo integradas de Django se enumeran a continuación. También es posible escribir consultas de campo personalizadas para campos de modelos.
Como conveniencia, cuando no se proporciona un tipo de consulta (como en Entry.objects.get(id=14)), el tipo de consulta se asume como exact.
Coincidencia exacta. Si el valor proporcionado para la comparación es None, se interpretará como un SQL NULL (consulte isnull para más detalles).
Ejemplos:
Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)
Equivalentes de SQL:
SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;
Comparaciones de MySQL
En MySQL, la configuración de «collation» de una tabla de base de datos determina si las comparaciones exactas son sensibles a mayúsculas y minúsculas. Esto es un ajuste de la base de datos, no un ajuste de Django. Es posible configurar las tablas de MySQL para utilizar comparaciones sensibles a mayúsculas y minúsculas, pero se involucran algunos trade-offs. Para obtener más información sobre esto, consulte la sección collation en la documentación de bases de datos.
iexact¶Comparación exacta no sensible a mayúsculas y minúsculas. Si el valor proporcionado para la comparación es None, se interpretará como un SQL NULL (consulte isnull para obtener más detalles).
Ejemplo:
Blog.objects.get(name__iexact="beatles blog")
Blog.objects.get(name__iexact=None)
Equivalentes de SQL:
SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;
Nota que la primera consulta coincidirá con 'Beatles Blog', 'beatles blog', 'BeAtLes BLoG', etc.
Usuarios de SQLite
Al utilizar el backend de SQLite y cadenas no ASCII, ten en cuenta la nota de la base de datos sobre comparaciones de cadenas. SQLite no realiza coincidencias no sensibles a mayúsculas y minúsculas para cadenas no ASCII.
contiene¶Prueba de contención sensible a mayúsculas y minúsculas.
Ejemplo:
Entry.objects.get(headline__contains="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline LIKE '%Lennon%';
Nota que esta coincidirá con el titular 'Lennon honrado hoy' pero no con 'lennon honrado hoy'.
Usuarios de SQLite
SQLite no admite declaraciones LIKE sensibles a mayúsculas y minúsculas; contains actúa como icontains para SQLite. Consulte la nota de la base de datos para obtener más información.
icontains¶Prueba case-insensible de contención.
Ejemplo:
Entry.objects.get(headline__icontains="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline ILIKE '%Lennon%';
Usuarios de SQLite
Al utilizar el backend SQLite y cadenas no ASCII, ten en cuenta la nota del base de datos sobre comparaciones de cadenas.
in¶En un iterable dado; a menudo una lista, tupla o conjunto de consultas. No es un caso de uso común, pero las cadenas (siendo iterables) se aceptan.
Ejemplos:
Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in="abc")
Equivalentes de SQL:
SELECT ... WHERE id IN (1, 3, 4);
SELECT ... WHERE headline IN ('a', 'b', 'c');
También puedes utilizar un conjunto de consultas para evaluar dinámicamente la lista de valores en lugar de proporcionar una lista de valores literales:
inner_qs = Blog.objects.filter(name__contains="Cheddar")
entries = Entry.objects.filter(blog__in=inner_qs)
Esta consulta de conjunto se evaluará como declaración de subselección:
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
Si pasas un QuerySet resultante de values() o values_list() como el valor a la búsqueda __in, debes asegurarte de que solo extraigas una columna en el resultado. Por ejemplo, esta funcionará (filtrando por los nombres del blog):
inner_qs = Blog.objects.filter(name__contains="Ch").values("name")
entries = Entry.objects.filter(blog__name__in=inner_qs)
Este ejemplo levantará una excepción, ya que la consulta interna está tratando de extraer dos valores de columnas, donde solo se espera uno:
# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains="Ch").values("name", "id")
entries = Entry.objects.filter(blog__name__in=inner_qs)
Consideraciones de rendimiento
Ten en cuenta el uso de consultas anidadas y comprende las características de rendimiento de tu servidor de base de datos (si tienes dudas, realiza pruebas!). Algunos backends de bases de datos, sobre todo MySQL, no optimizan muy bien las consultas anidadas. Es más eficiente, en esos casos, extraer una lista de valores y luego pasar esa lista a la segunda consulta. Es decir, ejecuta dos consultas en lugar de una:
values = Blog.objects.filter(name__contains="Cheddar").values_list("pk", flat=True)
entries = Entry.objects.filter(blog__in=list(values))
Ten en cuenta la llamada a list() alrededor del conjunto de consultas Blog para forzar la ejecución de la primera consulta. Sin ella, se ejecutaría una consulta anidada, porque los conjuntos de consultas son lazy.
Mayor que.
Ejemplo:
Entry.objects.filter(id__gt=4)
Equivalente en SQL:
SELECT ... WHERE id > 4;
Mayor o igual a.
Menor que.
Menor o igual a.
startswith¶Comienza con (sensible a mayúsculas y minúsculas).
Ejemplo:
Entry.objects.filter(headline__startswith="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline LIKE 'Lennon%';
SQLite no admite sentencias LIKE sensibles a mayúsculas y minúsculas; startswith actúa como istartswith para SQLite.
istartswith¶Comienza con (insensible a mayúsculas y minúsculas).
Ejemplo:
Entry.objects.filter(headline__istartswith="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline ILIKE 'Lennon%';
Usuarios de SQLite
Al utilizar el backend SQLite y cadenas no ASCII, ten en cuenta la nota del base de datos sobre comparaciones de cadenas.
endswith¶Termina con (sensible a mayúsculas y minúsculas).
Ejemplo:
Entry.objects.filter(headline__endswith="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline LIKE '%Lennon';
Usuarios de SQLite
SQLite no admite sentencias LIKE sensibles a mayúsculas y minúsculas; endswith actúa como iendswith para SQLite. Consulte la documentación del nota de base de datos para más información.
iendswith¶Termina con (insensible a mayúsculas y minúsculas).
Ejemplo:
Entry.objects.filter(headline__iendswith="Lennon")
Equivalente en SQL:
SELECT ... WHERE headline ILIKE '%Lennon'
Usuarios de SQLite
Al utilizar el backend SQLite y cadenas no ASCII, ten en cuenta la nota del base de datos sobre comparaciones de cadenas.
range¶Prueba de rango (inclusive).
Ejemplo:
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))
Equivalente en SQL:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
Puedes usar range en cualquier lugar donde puedas usar BETWEEN en SQL — para fechas, números y hasta caracteres.
Advertencia
Los textos traducidos son:
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
En general, no puedes mezclar fechas y fechas/horas.
date¶Para campos de fechas/hora, convierte el valor en fecha. Permite agregar consultas adicionales de campo. Recibe un valor de fecha.
Ejemplo:
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Cuando USE_TZ es True, los campos se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
year¶Para campos de fecha y fechas/hora, una coincidencia exacta del año. Permite agregar consultas adicionales de campo. Recibe un año entero.
Ejemplo:
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
Equivalente en SQL:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
iso_year¶Para campos de fecha y hora, un año ISO 8601 coincidente con el número de semana exacto. Permite la concatenación de consultas adicionales de campo. Recibe un año entero.
Ejemplo:
Entry.objects.filter(pub_date__iso_year=2005)
Entry.objects.filter(pub_date__iso_year__gte=2005)
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
month¶Para campos de fecha y hora, una coincidencia de mes exacta. Permite la concatenación de consultas adicionales de campo. Recibe un número entero del 1 (enero) al 12 (diciembre).
Ejemplo:
Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)
Equivalente en SQL:
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
day¶Para campos de fecha y hora, una coincidencia de día exacta. Permite la concatenación de consultas adicionales de campo. Recibe un día entero.
Ejemplo:
Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)
Equivalente en SQL:
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Nota que esto coincidirá con cualquier registro que tenga una fecha de publicación en el tercer día del mes, como 3 de enero, 3 de julio, etc.
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
week¶Para campos de fecha y hora, devuelve el número de semana (1-52 o 53) según ISO-8601, es decir, las semanas comienzan en un lunes y la primera semana contiene el primer jueves del año.
Ejemplo:
Entry.objects.filter(pub_date__week=52)
Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
week_day¶Los textos traducidos son:
Toma un valor entero que representa el día de la semana del 1 (domingo) al 7 (sábado).
Ejemplo:
Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Ten en cuenta que coincidirá con cualquier registro que tenga una pub_date que caiga en un lunes (día 2 de la semana), sin importar el mes o año en el que ocurra. Los días de la semana están indexados con el día 1 siendo domingo y el día 7 siendo sábado.
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
iso_week_day¶Para campos de fecha y hora, una coincidencia exacta del día de la semana ISO 8601. Permite encadenar consultas adicionales de campo.
Toma un valor entero que representa el día de la semana del 1 (lunes) al 7 (domingo).
Ejemplo:
Entry.objects.filter(pub_date__iso_week_day=1)
Entry.objects.filter(pub_date__iso_week_day__gte=1)
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Ten en cuenta que coincidirá con cualquier registro que tenga una pub_date que caiga en un lunes (día 1 de la semana), sin importar el mes o año en el que ocurra. Los días de la semana están indexados con el día 1 siendo lunes y el día 7 siendo domingo.
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
cuartal¶Para campos de fecha y hora, una coincidencia con el “cuartal del año”. Permite encadenar consultas adicionales de campo. Toma un valor entero entre 1 y 4 que representa el cuartal del año.
Ejemplo para recuperar entradas en el segundo cuartal (del 1 de abril al 30 de junio):
Entry.objects.filter(pub_date__quarter=2)
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
hora¶Para campos de fecha y hora, convierte el valor en hora. Permite encadenar consultas adicionales de campo. Toma un valor datetime.time.
Ejemplo:
Entry.objects.filter(pub_date__time=datetime.time(14, 30))
Entry.objects.filter(pub_date__time__range=(datetime.time(8), datetime.time(17)))
(No se incluye fragmento de código SQL equivalente para esta consulta porque la implementación de la consulta relevante varía entre diferentes motores de bases de datos.)
Cuando USE_TZ es True, los campos se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
hora¶Para campos de fecha y hora, coincidencia exacta con la hora. Permite encadenar consultas adicionales de campo. Toma un entero entre 0 y 23.
Ejemplo:
Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)
Equivalente en SQL:
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
minuto¶Para campos de fecha y hora, coincidencia exacta con el minuto. Permite encadenar consultas adicionales de campo. Toma un entero entre 0 y 59.
Ejemplo:
Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)
Equivalente en SQL:
SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
segundo¶Para campos de fecha y hora, coincidencia exacta con el segundo. Permite encadenar consultas adicionales de campo. Toma un entero entre 0 y 59.
Ejemplo:
Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)
Equivalente en SQL:
SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';
(El sintaxis SQL exacto varía para cada motor de bases de datos.)
Cuando USE_TZ es True, los campos de fechas/hora se convierten a la zona horaria actual antes de filtrar. Esto requiere definiciones de zona horaria en la base de datos.
isnull¶Toma True o False, que corresponden a las consultas SQL IS NULL y IS NOT NULL, respectivamente.
Ejemplo:
Entry.objects.filter(pub_date__isnull=True)
Equivalente en SQL:
SELECT ... WHERE pub_date IS NULL;
regex¶Búsqueda regular sensible al caso.
La sintaxis de la expresión regular es la del motor de base de datos en uso. En el caso de SQLite, que no tiene soporte integrado para expresiones regulares, esta función se proporciona mediante una (Python) función definida por el usuario REGEXP y la sintaxis de la expresión regular es, por tanto, la del módulo re de Python.
Ejemplo:
Entry.objects.get(title__regex=r"^(An?|The) +")
Equivalentes de SQL:
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle
SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite
Se recomienda utilizar cadenas brutas (por ejemplo, r'foo' en lugar de 'foo') para pasar la sintaxis de la expresión regular.
iregex¶Búsqueda regular insensible al caso.
Ejemplo:
Entry.objects.get(title__iregex=r"^(an?|the) +")
Equivalentes de SQL:
SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL
SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle
SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL
SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite
Django proporciona las siguientes funciones de agregación en el módulo django.db.models. Para obtener detalles sobre cómo utilizar estas funciones de agregación, consulte la guía sobre agregación. Consulte la documentación de la clase Aggregate para aprender a crear tus propias agregaciones.
Advertencia
SQLite no puede manejar la agregación en campos fecha/hora por defecto. Esto se debe a que SQLite no tiene campos fecha/hora nativos y Django emula actualmente estas características utilizando un campo de texto. Los intentos de utilizar la agregación en campos fecha/hora en SQLite provocarán una NotSupportedError.
Querysets o grupos vacíos
Los textos traducidos son:
Todos los agregados tienen los siguientes parámetros en común:
expressiones¶Cadenas que se refieren a campos del modelo, transformaciones de campo o expresiones de consulta.
output_field¶Un argumento opcional que representa el campo del modelo del valor de retorno
Nota
Cuando se combinan múltiples tipos de campos, Django solo puede determinar el output_field si todos los campos son del mismo tipo. De lo contrario, debes proporcionar el output_field tú mismo.
filter¶Un objeto Q opcional que se utiliza para filtrar las filas que se agrupan.
Consulte agregación condicional y filtrado en anotaciones para ejemplo de uso.
default¶Un argumento opcional que permite especificar un valor para usar como valor por defecto cuando el conjunto de consultas (o agrupación) contiene ninguna entrada.
Argumentos de palabra clave que pueden proporcionar contexto adicional para la SQL generada por el agregado.
Avg¶Devuelve el valor medio del expresión dada, que debe ser numérica a menos que especifiques un campo output_field diferente.
Alias predeterminado: <field>__avg
Tipo de retorno: float si la entrada es int, en otro caso el mismo tipo de campo de entrada o output_field si se proporciona. Si la consulta o agrupación está vacía, se devuelve default.
Opcional. Si distinct=True, Avg devuelve el valor medio de valores únicos. Esto es equivalente a la SQL AVG(DISTINCT <field>). El valor predeterminado es False.
Count¶Devuelve el número de objetos que están relacionados a través de la expresión proporcionada. Count('*') es equivalente a la expresión SQL COUNT(*).
Alias predeterminado: <field>__count
Tipo de retorno: int
Opcional. Si distinct=True, el recuento solo incluirá instancias únicas. Esto es equivalente a SQL COUNT(DISTINCT <field>). El valor por defecto es False.
Nota
No se admite el argumento default.
Devuelve el valor máximo de la expresión dada.
Alias predeterminado: <campo>__max
Tipo de retorno: mismo que el campo de entrada, o output_field si se proporciona. Si el conjunto de resultados o agrupación está vacío, se devuelve default.
Devuelve el valor mínimo de la expresión dada.
Alias predeterminado: <campo>__min
Tipo de retorno: mismo que el campo de entrada, o output_field si se proporciona. Si el conjunto de resultados o agrupación está vacío, se devuelve default.
Returns the desviación estándar de los datos en la expresión proporcionada.
Alias por defecto: <campo>__stddev
Tipo de retorno: float si la entrada es int, en otro caso el mismo tipo de campo de entrada o output_field si se proporciona. Si la consulta o agrupación está vacía, se devuelve default.
Opcional. Por defecto, StdDev devuelve la desviación estándar de población. Sin embargo, si sample=True, el valor de retorno será la desviación estándar muestral.
Sum¶Computa la suma de todos los valores de la expresión dada.
Alias por defecto: <field>__sum
Tipo de retorno: mismo que el campo de entrada, o output_field si se proporciona. Si el conjunto de resultados o agrupación está vacío, se devuelve default.
Opcional. Si distinct=True, Sum devuelve la suma de valores únicos. Esto es equivalente a SQL SUM(DISTINCT <campo>). El valor predeterminado es False.
Variance¶Devuelve la varianza de los datos en la expresión proporcionada.
Alias por defecto: <field>__variance
Tipo de retorno: float si la entrada es int, en otro caso el mismo tipo de campo de entrada o output_field si se proporciona. Si la consulta o agrupación está vacía, se devuelve default.
Optional. Por defecto, Variance devuelve la varianza poblacional. Sin embargo, si sample=True, el valor de retorno será la varianza muestral.
may 31, 2026