1. 介绍
aggregate:聚合
annotate:分组
Django的aggregate和annotate方法属于高级查询方法,主要用于组合查询。
当我们需要对查询集(queryset)的某些字段,进行计算,或进行先分组,再计算或排序, 我们就需要使用aggregate和annotate方法了。
一般搭配聚合函数进行使用。
model.py
from django.db import models
class Tag(models.Model):
name = models.CharField(verbose_name='标签名称', max_length=225)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(verbose_name='标题', max_length=225)
content = models.CharField(verbose_name='内容', max_length=225)
# 外键
tag = models.ManyToManyField(verbose_name='标签', to='Tag', related_name='tag_article')
price = models.DecimalField(max_digits=4, decimal_places=2)
def __str__(self):
return self.title
2. aggregate使用
2.1 基础使用
from django.db.models import F, Max, Min, Avg
from blog import models
# 计算所有文章价格的平均值 # {'price__avg': Decimal('50.000000')}
article_queryset = models.Article.objects.all().aggregate(Avg('price'))
2.2 其他使用
# 计算所有文章价格的总价钱 ,并其名称叫sum_price # {'sum_price': Decimal('250.00')}
article_queryset = models.Article.objects.aggregate(sum_price=Sum('price'))
# 文章最大价格 # {'max_price': Decimal('50.00')}
article_queryset = models.Article.objects.aggregate(max_price=Max('price'))
# # 同时获取文章价格的平均值, 价格的总价钱, 文章最大价格 # {'price_avg': Decimal('50.000000'), 'price_sum': Decimal('250.00'), 'price_max': Decimal('50.00')}
article_queryset = models.Article.objects.aggregate(price_avg=Avg('price'), price_sum=Sum('price'),
price_max=Max('price'))
# 根据标签反查文章的最大价格 # {'max_price': Decimal('50.00')}
article_queryset = models.Tag.objects.filter(id=1).first().tag_article.all().aggregate(max_price=Max('price'))
print(article_queryset)
3. annotate
3.1 基础使用
# 基础使用(配合values使用)
# 按标签名称分组,再统计每组文章的最大价格
# <QuerySet [{'name': '中国台湾省', 'tag_article__price__max': Decimal('50.00')}, {'name': '东京', 'tag_article__price__max': Decimal('80.00')}]>
article_queryset = models.Tag.objects.values('name').annotate(Max('tag_article__price'))
# 按文章标题进行分组,统计每个文章下面有多少标签
# <QuerySet [{'title': '二货的108种吃法', 'tag__count': 1}, {'title': '108种武功秘籍', 'tag__count': 5},
# {'title': 'fas', 'tag__count': 1}, {'title': '凤梨的108种吃法', 'tag__count': 1}]>
article_queryset = models.Article.objects.values('title').annotate(Count('tag'))
# 按文章标题进行分组,统计每个文章下面有多少标签,并定义返回的数据名称
article_queryset = models.Article.objects.values('title').annotate(tag_count=Count('tag'))
# 按标签名称分组,再统计每组文章数量
article_queryset = models.Tag.objects.values('name').annotate(Count('tag_article'))
# Annotate方法与Filter方法联用
# 先按标签名称分组,再统计每组文章数量, 然后筛选出文章数量大于1的数据
# <QuerySet [{'name': '中国台湾省', 'article_count': 5}, {'name': '东京', 'article_count': 3}]>
article_queryset = models.Tag.objects.values('name').annotate(article_count=Count('tag_article')).filter(
article_count__gt=1)
# Annotate方法与order_by
# 先按标签名称分组,再统计每组文章数量, 然后筛选出文章数量大于1的数据,最后以id倒叙排列
article_queryset = models.Tag.objects.values('name').annotate(article_count=Count('tag_article')).filter(
article_count__gt=1).order_by('-id')
# 分组聚合联合使用
# 先按标签名称分组,再统计每组文章数量, 然后筛选出文章数量大于1的数据,最后以id倒叙排列,取出标签id最大值
article_queryset = models.Tag.objects.values('name').annotate(article_count=Count('tag_article')).filter(
article_count__gt=1).order_by('-id').aggregate(Max('id'))
本文借鉴
(2条消息) aggregate和annotate方法使用详解与示例_weixin_33970449的博客-CSDN博客