Django ORM – Exemples multi-tables (Agrégation et requêtes groupées)
Requêtes d'agrégation (aggregate)
Les fonctions de requête d'agrégation effectuent des calculs sur un ensemble de valeurs et renvoient une seule valeur.
Avant d'utiliser des requêtes d'agrégation dans Django, vous devez d'abord importer Avg, Max, Min, Count, Sum (en majuscules) depuis django.db.models.
from django.db.models import Avg,Max,Min,Count,Sum # 引入函数
La valeur de retour d'une requête d'agrégation est de type dictionnaire.
La fonction aggregate() est une clause terminale pour QuerySet, produisant une valeur de synthèse, équivalente à count().
Après avoir utilisé aggregate(), le type de données devient un dictionnaire, et vous ne pouvez plus utiliser certaines API du type de données QuerySet.
Le type de données date (DateField) peut utiliser Max et Min.
Dans le dictionnaire renvoyé : le nom de clé est par défaut (nom de l’attribut suivi de __ puis du nom de la fonction d’agrégation), et la valeur est la valeur agrégée calculée.
Si vous souhaitez personnaliser le nom de clé dans le dictionnaire renvoyé, vous pouvez définir un alias :
aggregate(别名 = 聚合函数名("属性名称"))
Calculez le prix moyen de tous les livres :
Exemple
...
res = models.Book.objects.aggregate(Avg("price"))
print(res, type(res))
...

Calculez le nombre total de tous les livres, le prix le plus élevé et le prix le plus bas :
Exemple
print(res,type(res)

Requêtes groupées (annotate)
Les requêtes groupées utilisent généralement des fonctions d’agrégation, donc avant de les utiliser, vous devez importer Avg, Max, Min, Count, Sum (avec majuscule) depuis django.db.models.
from django.db.models import Avg,Max,Min,Count,Sum # 引入函数
Valeur de retour :
- Après regroupement, si vous utilisez values pour récupérer des valeurs, la valeur de retour est un type de données QuerySet contenant des dictionnaires.
- Après regroupement, si vous utilisez values_list pour récupérer des valeurs, la valeur de retour est un type de données QuerySet contenant des tuples.
Dans MySQL, la clause limit est équivalente à un découpage du type de données QuerySet dans l'ORM.
Remarque :
Placez les fonctions d'agrégation à l'intérieur de annotate.
-
Placez values ou values_list avant annotate :values ou values_list déclare les champs selon lesquels regrouper, et annotate effectue le regroupement.
-
values ou values_list placés après annotate :annotate signifie regrouper directement par la pk de la table courante ; values ou values_list indique quels champs interroger, et vous devez donner un alias aux fonctions d'agrégation dans annotate, puis écrire ces alias dans values ou values_list.
Préparez les données et créez les modèles
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)
Données :
Exécuter dans la ligne de commande MySQL :
Calculez le prix du livre le moins cher pour chaque éditeur :
Exemple
print(res)
La sortie suivante peut être vue dans la ligne de commande :
<QuerySet [{'name': 'Example出版社', 'in_price': Decimal('100.00')}, {'name': '明教出版社', 'in_price': Decimal('300.00')}]>

Comptez le nombre d'auteurs pour chaque livre :
Exemple
print(res)
<QuerySet [{'title': 'Example', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>

Comptez le nombre d'auteurs pour chaque livre dont le titre commence par "dish" :
Exemple
print(res)

Comptez les titres des livres ayant plus d'un auteur :
Exemple
print(res)
<QuerySet [{'title': 'Example', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>

Trier le QuerySet par ordre décroissant en fonction du nombre d'auteurs de chaque livre :
Exemple
print(res)

Interroger le prix total des livres publiés par chaque auteur :
Exemple
print(res)

Requête F()
Une instance de F() peut référencer des champs dans une requête pour comparer les valeurs de deux champs différents dans la même instance de modèle.
Les filtres construits précédemment ne comparent que les valeurs de champs avec une constante. Si vous voulez comparer les valeurs de deux champs, vous devez utiliser F().
Avant de l'utiliser, vous devez d'abord importer F depuis django.db.models.
from django.db.models import F
Utilisation :
F("字段名称")
F obtient dynamiquement la valeur d'un champ d'un objet et peut effectuer des opérations.
Django prend en charge les opérations d'addition, de soustraction, de multiplication, de division et de modulo entre des objets F(), et entre des objets F() et des constantes.
L'opération de mise à jour peut également utiliser la fonction F().
Interroger les personnes dont le salaire est supérieur à leur âge :
Exemple
...
book=models.Emp.objects.filter(salary__gt=F("age")).values("name","age")
...

Augmenter le prix de chaque livre de 100 yuan :
Exemple
print(res)

Requête Q()
Avant de l'utiliser, importez d'abord Q depuis django.db.models :from django.db.models import Q
Utilisation :
Q(条件判断)
Par exemple :
Q(title__startswith="菜")
Les conditions multiples dans les filtres précédemment construits sont toutes liées par AND. Si vous devez exécuter des requêtes plus complexes (telles que des instructions OR), vous pouvez utiliser Q.
Les objets Q peuvent être combinés à l'aide des opérateurs &, |, ~ (AND, OR, NOT).
Priorité de la plus élevée à la plus faible : ~, &, |.
Vous pouvez mélanger des objets Q et des arguments nommés. Les objets Q et les arguments nommés sont combinés avec « and » (c.-à-d., traitez les virgules comme AND), mais les objets Q doivent être placés avant tous les arguments nommés.
Interrogez les noms et les prix des livres dont le prix est supérieur à 350 ou dont le nom commence par « dish ».
from django.db.models import QExemple
res=models.Book.objects.filter(Q(price__gt=350)|Q(title__startswith="dish")).values("title","price")
print(res)
...

Interrogez les livres dont le nom se termine par « dish » ou qui ne sont pas d'octobre 2010 :
Exemple
print(res)

Interrogez les livres dont la date de publication est en 2004 ou 1999, et dont le titre contient « dish ».
Mélangez des objets Q et des arguments nommés ; les objets Q doivent précéder tous les mots-clés :
Exemple
print(res)
