django的聚合函数和aggregate、annotate方法使用详解


Posted in Python onJuly 23, 2019

支持聚合函数的方法:

提到聚合函数,首先我们要知道的就是这些聚合函数是不能在django中单独使用的,要想在django中使用这些聚合函数,就必须把这些聚合函数放到支持他们的方法内去执行。支持聚合函数的方法有两种,分别是aggregate和annotate,这两种方法执行的原生SQL以及结果都有很大的区别,下面我们以实例操作的方式一一介绍:

# 示例模型:

class Author(models.Model):


"""作者模型"""


name = models.CharField(max_length=100)


age = models.IntegerField()


email = models.EmailField() 


class Book(models.Model):


"""图书模型"""


name = models.CharField(max_length=100)


author = models.ForeignKey('Author',on_delete=models.CASCADE)


price = models.FloatField()


class BookOrder(models.Model):


"""图书订单模型"""


book = models.ForeignKey('Book',on_delete=models.CASCADE)


sailprice = models.FloatField()


create_time = models.DateTimeField(auto_now_add=True)

1、aggregate:这个方法时一个QuerySet对象的API,在执行聚合函数的时候,是对QuerySet整个对象的某个属性汇总,在汇总时不会使用该模型的主键进行group by进行分组,得到的是一个结果字典。同时,该方法支持聚合关联表(如使用ForeignKey)中的字段,在聚合连表中字段时,传递该字段的方式与查询连表时传递字段的方式相同,会使用到"__"。示例代码如下:

from django.db.models import Avg

from django.db import connection

1、对当前表中数据进行聚合:

result = Author.objects.aggregate(avg_age=Avg('age'))

print(connection.queries)	
# 打印执行时所有的查询语句

2、对连表中数据进行聚合:

result = Book.objects.aggregate(sum=Sum('bookorder__price'))

2、annotate:这个方法不但可以执行聚合函数,也可以传递F、Q对象为当前QuerySet生成一个新的属性。

这个方法一般聚合的是连表中的字段,会为当前QuerySet中的每个对象生成一个独立的摘要,为查询的模型增加一个新的属性,这个属性的值就是使用聚合函数所得到的值,在使用这个聚合函数的时候annotate会使用这个模型的主键进行group by进行分组(注意这里只有在使用聚合函数生成新字段的时候会进行group by,在使用F、Q表达式增添新字段时,并不会使用group by),然后在连表中根据分组的结果进行聚合,这一点正符合为QuerySet中每个对象增加一个独立摘要的事实。

使用这个方法执行聚合函数,得到的结果是一个QuerySet对象,结果依然能够调用filter()、order_by()甚至annotate()进行再次聚合,现在我想提取每一本书的平均销售的价格(注意销售价格在BookOrder表中):

from django.db.models import Avg

from django.db import connection 


books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))

for book in books:

print('%s/%s'%(book.name,book.avg))
	# 注意这里的avg属性就是annotate执行聚合函数得到的

print(connection.queries)

聚合函数:

在Django中,聚合函数都是在django.db.models模块下的,具体的聚合函数有Avg、Count、Max、Min、Sum,现在我们一一介绍这些函数的作用:

1、Avg:计算平均值,使用于与数值相关的字段,如果使用aggregate方法来执行这个函数,那么会得到一个字典,默认情况下,字典的键为field__avg,值为执行这个聚合函数所得到的值,示例代码如下:

# 计算所有作者的平均年龄

result = Author.objects.aggregate(Avg('age'))

print(result)	# 结果为:{"age__avg": 23.8}


# 如果想要使用自定义的键,那么可以把aggregate中的未知参数变为关键字参数,该关键字就是得到的键,示例代码如下:

result = Author.objects.aggregate(avgAge=Avg('age'))

print(result)	# 结果为:{"avgAge": 23.8} 


# 如果使用annotate方法执行这个函数,那么得到的结果就是一个QuerySet对象,只不过这个对象中的每一个都会添加一个属性,这个属性的名称其实和上面的键一样,可以使用默认也可以自定义,使用方法与在aggregate中键名的定义一样,这里就不再赘述:	

books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))

for book in books:


print('%s/%s'%(book.name,book.avg))	# 注意这里的avg属性就是annotate执行聚合函数得到的

print(connection.queries)

2、Count:计算数量,基本用法与Avg相同,在使用这个聚合函数的时候可以传递一个distinct参数用来去重:

# 计算总共有多少个订单

result = BookOrder.objects.aggregate(total=Count('id',distanct=True))

print(result)	# 结果为:{"total": 18}
 

# 计算每本书的订单量

books = Book.objects.annotate(total=Count('bookorder__id'))

for book in books:

print('%s/%s'%(book.name,book.total))

3、Max和Min:计算某个字段的最大值和最小值,用法与Avg一样

4、Sum:计算总和,用法与Avg一样

注:总结一下,其实可以简单的理解使用aggregate时,是对QuerySet整个对象的某个属性汇总聚合,不会使用分组。而使用annotate方法时,是为QuerySet中的每个对象生成一个独立的摘要,一定会使用分组,然后再聚合

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 Python
简单讲解Python编程中namedtuple类的用法
Jun 21 Python
python 网络编程详解及简单实例
Apr 25 Python
django admin添加数据自动记录user到表中的实现方法
Jan 05 Python
手把手教你用python抢票回家过年(代码简单)
Jan 21 Python
Python 创建空的list,以及append用法讲解
May 04 Python
利用Python如何制作好玩的GIF动图详解
Jul 11 Python
python 自动轨迹绘制的实例代码
Jul 05 Python
详解PyTorch中Tensor的高阶操作
Aug 18 Python
python 协程 gevent原理与用法分析
Nov 22 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
Mar 18 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
Jun 12 Python
PyCharm 配置远程python解释器和在本地修改服务器代码
Jul 23 #Python
python实现DEM数据的阴影生成的方法
Jul 23 #Python
Django REST framework 如何实现内置访问频率控制
Jul 23 #Python
详解pandas中MultiIndex和对象实际索引不一致问题
Jul 23 #Python
python视频按帧截取图片工具
Jul 23 #Python
python如何实现从视频中提取每秒图片
Oct 22 #Python
详解Django 时间与时区设置问题
Jul 23 #Python
You might like
php守护进程 加linux命令nohup实现任务每秒执行一次
2011/07/04 PHP
吐槽一下我所了解的Node.js
2014/10/08 Javascript
AngularJS使用angular-formly进行表单验证
2015/12/27 Javascript
javascript类型系统 Window对象学习笔记
2016/01/07 Javascript
jQuery实现给input绑定回车事件的方法
2017/02/09 Javascript
Bootstrap 响应式实用工具实例详解
2017/03/29 Javascript
Angular实现图片裁剪工具ngImgCrop实践
2017/08/17 Javascript
JS库 Highlightjs 添加代码行号的实现代码
2017/09/13 Javascript
LayUI动态设置checkbox不显示的解决方法
2019/09/02 Javascript
Vue+element-ui添加自定义右键菜单的方法示例
2020/12/08 Vue.js
[56:46]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 VP vs Effect
2018/04/01 DOTA
Python实现的简单dns查询功能示例
2017/05/24 Python
Python3 操作符重载方法示例
2017/11/23 Python
解决python3中解压zip文件是文件名乱码的问题
2018/03/22 Python
对python numpy数组中冒号的使用方法详解
2018/04/17 Python
python高效过滤出文件夹下指定文件名结尾的文件实例
2018/10/21 Python
Python numpy.array()生成相同元素数组的示例
2018/11/12 Python
python监测当前联网状态并连接的实例
2018/12/18 Python
Django 日志配置按日期滚动的方法
2019/01/31 Python
Python3.7 新特性之dataclass装饰器
2019/05/27 Python
基于MATLAB和Python实现MFCC特征参数提取
2019/08/13 Python
让你的Python代码实现类型提示功能
2019/11/19 Python
互动出版网:专业书籍
2017/03/21 全球购物
美国知名的家庭连锁百货商店:Boscov’s
2017/07/27 全球购物
在线吉他课程,学习如何弹吉他:Fender Play
2019/02/28 全球购物
internal修饰符起什么作用
2013/12/16 面试题
建筑自我鉴定
2013/10/19 职场文书
大学生写自荐信的技巧
2014/01/08 职场文书
个人党性剖析材料
2014/02/03 职场文书
国际贸易毕业生自荐书
2014/06/22 职场文书
副总经理党的群众路线教育实践活动个人对照检查材料思想汇报
2014/10/06 职场文书
2014年体育教学工作总结
2014/12/09 职场文书
欢迎词范文
2015/01/27 职场文书
Nginx配置80端口访问8080及项目名地址方法解析
2021/03/31 Servers
Centos环境下Postgresql 安装配置及环境变量配置技巧
2021/05/18 PostgreSQL
Mysql索引失效 数据库表中有索引还是查询很慢
2022/05/15 MySQL