【Django】聚合查询——连接和聚合

小明 2025-05-06 21:57:19 5

还���以下面的模型为例进行讨论,给出示例代码和示例结果

()
from django.db import models
class Author(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
class Publisher(models.Model):
    name = models.CharField(max_length=300)
class Book(models.Model):
    name = models.CharField(max_length=300)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    rating = models.FloatField()
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    pubdate = models.DateField()
class Store(models.Model):
    name = models.CharField(max_length=300)
    books = models.ManyToManyField(Book)

正向查询

如果需要聚合查询某个模型相关联的其他模型的字段,我们要使用__(双下划线)。

找出每家商店提供的书籍价格范围:

()
>>> from django.db.models import Max, Min
>>> Store.objects.annotate(min_price=Min("books__price"), max_price=Max("books__price"))

这个规则也适用于aggregate(),找出所有商店在售书籍中的最低价格和最高价格:

>>> Store.objects.aggregate(min_price=Min("books__price"), max_price=Max("books__price"))
{'min_price': Decimal('5.00'), 'max_price': Decimal('30.00')}

还可以进行链式连接,找出在售书籍中最年轻作者的年龄:

>>> Store.objects.aggregate(youngest_age=Min("books__authors__age"))
{'youngest_age': 10}

反向查询

查询所有出版社,计算各自的书籍库存数量:

>>> from django.db.models import Avg, Count, Min, Sum
>>> Publisher.objects.annotate(Count("book"))

>>> publishers = Publisher.objects.annotate(Count("book"))
>>> publishers[0].book__count
1

可以观察到查询结果里的每一个 Publisher 会有多余的属性—— book__count

要找到所有出版商管理的书籍中最老的一本书的出版日期:

>>> Publisher.objects.aggregate(oldest_pubdate=Min("book__pubdate"))
{'oldest_pubdate': datetime.date(2024, 3, 1)}

查询所有作者,并得到他所著书籍的总页数:

>>> Author.objects.annotate(total_pages=Sum("book__pages"))

要找到所有作者所著书籍的平均评分:

>>> Author.objects.aggregate(average_rating=Avg("book__rating"))
{'average_rating': 9.0}
The End
微信