Django ORM – Ejemplos de varias tablas (consultas de agregación y agrupación)
Consulta de agregación (aggregate)
La función de consulta de agregación realiza cálculos sobre un conjunto de valores y devuelve un único valor.
Antes de usar consultas de agregación en Django, primero se deben importar Avg, Max, Min, Count, Sum desde django.db.models (con la primera letra en mayúscula).
from django.db.models import Avg,Max,Min,Count,Sum # 引入函数
El tipo de dato devuelto por la consulta de agregación es un diccionario.
La función de agregación aggregate() es una cláusula terminal de QuerySet que genera un valor resumido, equivalente a count().
Después de usar aggregate(), el tipo de dato se convierte en diccionario y ya no se pueden usar algunas API del tipo de dato QuerySet.
Para el tipo de dato de fecha (DateField) se pueden usar Max y Min.
En el diccionario devuelto: el nombre de la clave por defecto es (nombre del atributo más __nombre de la función de agregación), y el valor es el valor agregado calculado.
Si se desea personalizar el nombre de las claves del diccionario devuelto, se puede usar un alias:
aggregate(别名 = 聚合函数名("属性名称"))
Calcular el precio medio de todos los libros:
Ejemplo
...
res = models.Book.objects.aggregate(Avg("price"))
print(res, type(res))
...

Calcular la cantidad total de libros, el precio más caro y el precio más barato:
Ejemplo
print(res,type(res)

Consulta de agrupación (annotate)
La consulta de agrupación generalmente usa funciones de agregación, por lo que antes de usarla se deben importar Avg, Max, Min, Count, Sum desde django.db.models (con la primera letra en mayúscula).
from django.db.models import Avg,Max,Min,Count,Sum # 引入函数
Valor de retorno:
- Después de agrupar, si se usa values para obtener los valores, el valor de retorno es de tipo QuerySet que contiene diccionarios;
- Después de agrupar, si se usa values_list para obtener los valores, el valor de retorno es de tipo QuerySet que contiene tuplas.
El limit en MySQL equivale a la segmentación (slice) del tipo de dato QuerySet en ORM.
Nota:
En annotate se colocan las funciones de agregación.
-
values o values_list se colocan antes de annotate:values o values_list declaran por qué campo se agrupa, y annotate ejecuta la agrupación.
-
values o values_list se colocan después de annotate:annotate indica agrupar directamente por la pk de la tabla actual; values o values_list indican qué campos consultar, y se debe asignar un alias a la función de agregación en annotate, escribiendo dicho alias en values o values_list.
Preparar los datos y crear los modelos
models.py
name = models.CharField(max_length=32)
age = models.IntegerField()
salary = models.DecimalField(max_digits=8, decimal_places=2)
dep = models.CharField(max_length=32)
province = models.CharField(max_length=32)
class Emps(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
salary = models.DecimalField(max_digits=8, decimal_places=2)
dep = models.ForeignKey("Dep", on_delete=models.CASCADE)
province = models.CharField(max_length=32)
class Dep(models.Model):
title = models.CharField(max_length=32)
Datos:
Ejecutar en la línea de comandos de MySQL:
Calcular el precio del libro más barato de cada editorial:
Ejemplo
print(res)
En la línea de comandos se puede ver la siguiente salida:
<QuerySet [{'name': 'Ejemplo出版社', 'in_price': Decimal('100.00')}, {'name': '明教出版社', 'in_price': Decimal('300.00')}]>

Contar el número de autores de cada libro:
Ejemplo
print(res)
<QuerySet [{'title': 'Ejemplo', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>

Contar el número de autores de los libros que comienzan con "菜":
Ejemplo
print(res)

Obtener los nombres de los libros que tienen más de un autor:
Ejemplo
print(res)
<QuerySet [{'title': 'Ejemplo', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>

Ordenar el QuerySet de forma descendente según la cantidad de autores de cada libro:
Ejemplo
print(res)

Consultar el precio total de los libros publicados por cada autor:
Ejemplo
print(res)

Consulta F()
Una instancia de F() puede hacer referencia a campos en una consulta para comparar los valores de dos campos distintos en la misma instancia de un model.
Los filtros construidos anteriormente solo comparaban el valor de un campo con una constante; si se desea comparar los valores de dos campos, es necesario usar F().
Antes de usarlo, se debe importar F desde django.db.models:
from django.db.models import F
Uso:
F("字段名称")
F obtiene dinámicamente el valor de los campos del objeto y puede realizar operaciones.
Django admite operaciones de suma, resta, multiplicación, división y módulo entre objetos F(), y entre objetos F() y constantes.
La operación de modificación (update) también puede usar la función F().
Consultar personas cuyo salario sea mayor que su edad:
Ejemplo
...
book=models.Emp.objects.filter(salary__gt=F("age")).values("name","age")
...

Aumentar el precio de cada libro en 100 yuanes:
Ejemplo
print(res)

Consulta Q()
Antes de usarlo, se debe importar Q desde django.db.models:from django.db.models import Q
Uso:
Q(条件判断)
Por ejemplo:
Q(title__startswith="菜")
En los filtros construidos anteriormente, la relación entre múltiples condiciones era siempre and; si se necesita ejecutar consultas más complejas (por ejemplo, con la sentencia or), se puede usar Q.
Los objetos Q se pueden combinar usando los operadores & | ~ (y, o, no).
La prioridad de mayor a menor es: ~ & |.
Se pueden mezclar objetos Q y parámetros de palabra clave; los objetos Q y los parámetros de palabra clave se combinan con "and" (es decir, la coma se considera and), pero los objetos Q deben colocarse delante de todos los parámetros de palabra clave.
Consultar el nombre y el precio de los libros cuyo precio sea mayor que 350 o cuyo nombre comience con "菜".
from django.db.models import QEjemplo
res=models.Book.objects.filter(Q(price__gt=350)|Q(title__startswith="plato")).values("title","price")
print(res)
...

Consultar los libros que terminan con "菜" o que no sean de octubre de 2010:
Ejemplo
print(res)

Consultar los libros cuya fecha de publicación sea de 2004 o 1999 y cuyo título contenga "verdura".
Uso mixto de objetos Q y parámetros de palabra clave; los objetos Q deben ir delante de todos los parámetros de palabra clave:
Ejemplo
print(res)
