django中aggregate和annotate的不同
结论:
1、两者都是进行聚合计算的
2、aggregate 计算所有QuerySet 对象的一个汇总值,返回的是一个dict,annotate为QuerySet中的每个对象生成一个汇总,返回的还是一个QuerySet对象。
3、如果转换成SQL语句的话:
aggregate :select count(*) from user
annotate :select count(*) from user group by gender
4、因为aggregate返回的是一个dict,是没有办法进行链式编程了,所以没有办法再接QuerySet对象的其他方法。
案例:
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)
aggregate 进行聚合计算
# 计算Book的总数 >>> Book.objects.count() 2452 #计算出版社为BaloneyPress的书的总数 >>> Book.objects.filter(publisher__name='BaloneyPress').count() 73 # 计算所有图书的平均价格 >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} # 获取最高图书价格 >>> from django.db.models import Max >>> Book.objects.all().aggregate(Max('price')) {'price__max': Decimal('81.20')} # 计算最高价格和平均价格的差 >>> from django.db.models import FloatField >>> Book.objects.aggregate( ... price_diff=Max('price', output_field=FloatField()) - Avg('price')) {'price_diff': 46.85}
annotate 进行聚合计算
>>> from django.db.models import Count #计算每个出版社的图书数量 >>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs <QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]> >>> pubs[0].num_books 73 # 求每个出版社书籍评分大约5分和小于5分的图书量 >>> from django.db.models import Q >>> above_5 = Count('book', filter=Q(book__rating__gt=5)) >>> below_5 = Count('book', filter=Q(book__rating__lte=5)) >>> pubs = Publisher.objects.annotate(below_5=below_5).annotate(above_5=above_5) >>> pubs[0].above_5 23 >>> pubs[0].below_5 12 # 求出版社出最多书的前五名 >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5] >>> pubs[0].num_books 1323
简单说明
django 提供两种产生聚合的方法
第一种aggregate 方法是产生整个结果集的总体统计值。
第二种方法,产生结果集中每个对象的独立的总体统计值。
注意,结果集有多少对象就生成多少个统计值,这是aggregate()与annotate()的主要区别。
理解这两个概念,就清楚怎么使用aggregate()与annotate()这两个函数了。
上面是简单理解
这两个函数除了在聚合方面存在差别以外,其实还是有很大的不同的。aggregate()只能支持聚合函数。annotate()支持functions下面的所有函数。
from django.db.models.functions import TruncMonth models.Test.objects # 这里是手工折行的 ^_^ .annotate(month=TruncMonth('timestamp')) # 把2021-11-11转换成2021-11 并把month放入QuerySet中 .values('month') # Group By month .annotate(c=Count('id')) # 根据month分组计数 并把c放入到QuerySet中 .values('month','c') # select month,c from QuerySet ==>QuerySet

浙公网安备 33010602011771号