Django Aggregation 使用指南

Django Aggregation 使用指南

在构建Django应用时,我们经常需要对数据库中的数据进行汇总或聚合操作。例如,计算某个字段的平均值、最大值或最小值。这篇文章将详细介绍如何在Django中使用聚合查询,并结合实例进行说明。

聚合查询简介

Django提供了强大的数据库查询API,可以创建、检索、更新和删除单个对象。除此之外,有时我们需要通过汇总或聚合对象集合来获取派生值。本文将介绍如何使用Django查询来生成和返回聚合值。

示例模型

我们以以下模型为例,这些模型用于跟踪一系列在线书店的库存:

python 复制代码
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)

常见聚合查询示例

以下是一些常见的聚合查询示例:

  1. 计算所有书籍的总数:

    python 复制代码
    Book.objects.count()
  2. 计算某出版社出版的书籍总数:

    python 复制代码
    Book.objects.filter(publisher__name="BaloneyPress").count()
  3. 计算所有书籍的平均价格:

    python 复制代码
    from django.db.models import Avg
    Book.objects.aggregate(Avg("price"))
  4. 计算所有书籍的最高价格:

    python 复制代码
    from django.db.models import Max
    Book.objects.aggregate(Max("price"))
  5. 计算每个出版社的书籍数量:

    python 复制代码
    from django.db.models import Count
    pubs = Publisher.objects.annotate(num_books=Count("book"))
  6. 按书籍数量排序的前5个出版社:

    python 复制代码
    pubs = Publisher.objects.annotate(num_books=Count("book")).order_by("-num_books")[:5]

聚合方法详解

Django提供了两种生成聚合值的方法:

  1. 对整个查询集生成汇总值:

    python 复制代码
    from django.db.models import Avg
    Book.objects.aggregate(Avg("price"))

    这将计算所有书籍价格的平均值。

  2. 对查询集中的每个对象生成独立的汇总值:

    python 复制代码
    from django.db.models import Count
    books = Book.objects.annotate(num_authors=Count("authors"))

    这将为每本书添加一个字段,表示其作者的数量。

高级用法

  1. 结合多个聚合:

    python 复制代码
    from django.db.models import Avg, Max, Min
    Book.objects.aggregate(Avg("price"), Max("price"), Min("price"))
  2. 基于注释值进行过滤:

    python 复制代码
    Book.objects.annotate(num_authors=Count("authors")).filter(num_authors__gt=1)
  3. 注释和过滤的顺序:

    注释和过滤的顺序对查询结果有很大影响。例如:

    python 复制代码
    Publisher.objects.annotate(num_books=Count("book")).filter(book__rating__gt=3.0)

    与:

    python 复制代码
    Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count("book"))

    这两种查询的结果可能会有所不同,因为注释和过滤的顺序不同。

结合具体实例

我们通过以下代码实现了对Twitter数据的聚合查询:

python 复制代码
from django.db.models import Count, Avg
from .models import TwAuthors, TwTweets

# 获取每个作者的平均推文数
authors = TwAuthors.objects.annotate(avg_tweets=Avg('twtweets__id'))

# 获取推文数量最多的前5个作者
top_authors = TwAuthors.objects.annotate(num_tweets=Count('twtweets')).order_by('-num_tweets')[:5]

这段代码展示了如何利用Django的聚合查询功能,获取每个作者的平均推文数,并找出推文数量最多的前5个作者。

annotateaggregate:区别

在Django中,annotateaggregate是用于生成汇总值的两种不同方法,主要区别在于它们的作用范围和结果类型。

1. annotate

  • 作用范围:对每个对象单独计算汇总值。
  • 返回结果:返回一个新的QuerySet,每个对象都会附带一个额外的属性,该属性是通过计算汇总值生成的。
  • 使用场景:当你需要对查询集中的每个对象进行汇总计算时使用。例如,你可能想知道每本书有多少个作者。
示例代码:
python 复制代码
from django.db.models import Count

# 查询每本书的作者数量
books = Book.objects.annotate(num_authors=Count('authors'))
for book in books:
    print(book.name, book.num_authors)

2. aggregate

  • 作用范围:对整个QuerySet进行汇总计算。
  • 返回结果:返回一个字典,键是汇总值的名称,值是计算的汇总值。
  • 使用场景:当你需要对整个查询集进行汇总计算时使用。例如,你可能想知道所有书籍的平均价格。
示例代码:
python 复制代码
from django.db.models import Avg

# 计算所有书籍的平均价格
average_price = Book.objects.aggregate(Avg('price'))
print(average_price)

结合实例

假设我们有一个包含书籍信息的数据库,并且我们想获取一些汇总信息:

使用annotate

我们想知道每个出版社出版的书籍数量:

python 复制代码
from django.db.models import Count

publishers = Publisher.objects.annotate(num_books=Count('book'))
for publisher in publishers:
    print(publisher.name, publisher.num_books)

每个Publisher对象将会有一个num_books属性,表示该出版社出版的书籍数量。

使用aggregate

我们想知道所有书籍的最高价格、最低价格和平均价格:

python 复制代码
from django.db.models import Avg, Max, Min

price_summary = Book.objects.aggregate(
    max_price=Max('price'),
    min_price=Min('price'),
    avg_price=Avg('price')
)
print(price_summary)

返回的price_summary是一个字典,包含了所有书籍的最高价格、最低价格和平均价格。

结论

Django的聚合查询功能非常强大,可以帮助我们高效地从数据库中提取所需的汇总数据。通过合理使用这些功能,我们可以大大简化数据统计和分析的工作。

希望这篇文章能帮助你更好地理解和使用Django的聚合查询。如果你有任何问题或建议,欢迎留言讨论。

相关推荐
blues_C1 天前
十三、【核心功能篇】测试计划管理:组织和编排测试用例
vue.js·django·测试用例·drf·测试平台
恸流失1 天前
DJango项目
后端·python·django
编程大全2 天前
41道Django高频题整理(附答案背诵版)
数据库·django·sqlite
网安小张2 天前
解锁FastAPI与MongoDB聚合管道的性能奥秘
数据库·python·django
KENYCHEN奉孝2 天前
Pandas和Django的示例Demo
python·django·pandas
老胖闲聊2 天前
Python Django完整教程与代码示例
数据库·python·django
noravinsc2 天前
django paramiko 跳转登录
后端·python·django
践行见远2 天前
django之请求处理过程分析
数据库·django·sqlite
声声codeGrandMaster2 天前
Django之表格上传
后端·python·django
菌菌的快乐生活2 天前
网站静态文件加速-Django项目静态文件存储到腾讯云COS存储提升网络请求速度
django·cos存储