aggregate和annotate方法使用

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博客

Django基础(24): aggregate和annotate方法使用详解与示例 (qq.com)

Django ORM中,`annotate()`和`aggregate()`都是用于对查询结果进行聚合操作的函数,但它们的作用和使用方式略有不同。 `annotate()`函数用于在每一行结果上进行聚合操作,生成一个新的字段,并将聚合结果添加到每一行中。通常,你会在`annotate()`中使用聚合函数(如`Count`、`Sum`、`Avg`等)来计算某个字段的聚合值。 以下是一个示例,展示了如何使用`annotate()`函数计算每个类别的商品数量: ```python from django.db.models import Count from myapp.models import Product result = Product.objects.values('category').annotate(count=Count('id')) ``` 在上面的示例中,我们假设有一个名为`category`的字段表示商品类别,以及一个自动生成的`id`字段表示商品的唯一标识。通过`.values('category')`指定按照`category`字段进行分组,并使用`.annotate(count=Count('id'))`计算每个类别中商品的数量,并将结果保存在新的字段`count`中。 相反,`aggregate()`函数用于对整个查询结果进行聚合操作,生成一个包含聚合结果的字典。通常,你会在`aggregate()`中使用聚合函数来计算整个查询结果的某个聚合值。 以下是一个示例,展示了如何使用`aggregate()`函数计算所有商品的总价格: ```python from django.db.models import Sum from myapp.models import Product result = Product.objects.aggregate(total_price=Sum('price')) ``` 在上面的示例中,我们假设有一个名为`price`的字段表示商品价格。使用`.aggregate(total_price=Sum('price'))`计算所有商品的总价格,并将结果保存在字典中,键为`total_price`。 总结一下,`annotate()`用于对每一行进行聚合操作并生成新的字段,而`aggregate()`用于对整个查询结果进行聚合操作并生成一个字典。 希望这可以帮助你理解`annotate()`和`aggregate()`函数在Django ORM中的区别和作用。如果有任何进一步的问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值