codecamp

Django4.0 聚合-在QuerySet中的每一个条目生成聚合

生成值的汇总的另一个办法是为 ​QuerySet ​的每一个对象生成独立汇总。比如,如果你想检索书籍列表,你可能想知道每一本书有多少作者。每一本书与作者有多对多的关系;我们想在 ​QuerySet ​中为每一本书总结这个关系。

使用 ​annotate()​ 子句可以生成每一个对象的汇总。当指定 ​annotate()​ 子句,​QuerySet ​中的每一个对象将对指定值进行汇总。

这些语法与用于 ​aggregate()​ 子句的语法相同。 annotate() 的每个参数都描述了一个要计算的聚合。 例如,用作者数量注释书籍:

# Build an annotated queryset
>>> from django.db.models import Count
>>> q = Book.objects.annotate(Count('authors'))
# Interrogate the first object in the queryset
>>> q[0]
<Book: The Definitive Guide to Django>
>>> q[0].authors__count
2
# Interrogate the second object in the queryset
>>> q[1]
<Book: Practical Django Projects>
>>> q[1].authors__count
1

与 ​aggregate()​ 一样,注解的名称是根据聚合函数和被聚合的字段名自动生成的。当你在指定注解的时候,你可以通过提供一个别名重写这个默认名:

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

与 ​aggregate()​ 不同的是,​annotate()​ 不是终端子句。​annotate()​ 子句的输出就是 ​QuerySet​;这个 ​QuerySet ​被其他 ​QuerySet ​操作进行修改,包括 ​filter()​, ​order_by()​ ,甚至可以对 ​annotate()​ 进行额外调用。

组合多个聚合

将多个聚合与​ annotate() ​组合会产生错误的结果,因为使用的是连接而不是子查询:

>>> book = Book.objects.first()
>>> book.authors.count()
2
>>> book.store_set.count()
3
>>> q = Book.objects.annotate(Count('authors'), Count('store'))
>>> q[0].authors__count
6
>>> q[0].store__count
6

对大部分聚合来说,没办法避免这个问题,但是,​Count ​聚合可以使用 ​distinct ​参数来避免:

>>> q = Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
>>> q[0].authors__count
2
>>> q[0].store__count
3


Django4.0 聚合-在QuerySet上生成聚合
Django4.0 聚合-连接(Joins)和聚合
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

Django4.0 模型和数据库

Django4.0 处理HTTP请求

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }