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 相关文章推荐
把项目从Python2.x移植到Python3.x的经验总结
Apr 20 Python
实例Python处理XML文件的方法
Aug 31 Python
python版本的读写锁操作方法
Apr 25 Python
Python列表和元组的定义与使用操作示例
Jul 26 Python
python 读取视频,处理后,实时计算帧数fps的方法
Jul 10 Python
Python2和Python3之间的str处理方式导致乱码的讲解
Jan 03 Python
Python常见数据结构之栈与队列用法示例
Jan 14 Python
浅谈python图片处理Image和skimage的区别
Aug 04 Python
jupyter notebook 多行输出实例
Apr 09 Python
flask项目集成swagger的方法
Dec 09 Python
详解分布式系统中如何用python实现Paxos
May 18 Python
python神经网络学习 使用Keras进行回归运算
May 04 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中路径问题的解决方案
2006/10/09 PHP
在Windows下编译适用于PHP 5.2.12及5.2.13的eAccelerator.dll(附下载)
2010/05/04 PHP
PHP+MYSQL会员系统的登陆即权限判断实现代码
2011/09/23 PHP
深入php之规范编程命名小结
2013/05/15 PHP
yii操作session实例简介
2014/07/31 PHP
WordPress中自定义后台管理界面配色方案的小技巧
2015/12/29 PHP
Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
2020/01/07 PHP
指定位置如果有图片显示图片,无图片显示广告的JS
2010/06/05 Javascript
Jquey拖拽控件Draggable使用方法(asp.net环境)
2010/09/28 Javascript
IE中jquery.form中ajax提交没反应解决方法分享
2012/09/11 Javascript
JavaScript中的函数的两种定义方式和函数变量赋值
2014/05/12 Javascript
jQuery中的read和JavaScript中的onload函数的区别
2014/08/27 Javascript
Jquery中find与each方法用法实例
2015/02/04 Javascript
基于Jquery实现焦点图淡出淡入效果
2015/11/30 Javascript
JavaScript中 ES6 generator数据类型详解
2016/08/11 Javascript
jQuery插件HighCharts绘制2D带Label的折线图效果示例【附demo源码下载】
2017/03/08 Javascript
Angular4如何自定义首屏的加载动画详解
2017/07/26 Javascript
详解基于webpack2.x的vue2.x的多页面站点
2017/08/21 Javascript
关于vue表单提交防双/多击的例子
2019/10/31 Javascript
vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)
2019/12/29 Javascript
js根据后缀判断文件文件类型的代码
2020/05/09 Javascript
win7 下搭建sublime的python开发环境的配置方法
2014/06/18 Python
使用httplib模块来制作Python下HTTP客户端的方法
2015/06/19 Python
Python简单连接MongoDB数据库的方法
2016/03/15 Python
Python SQLite3简介
2018/02/22 Python
Django实现学员管理系统
2019/02/26 Python
TensorFlow2.1.0最新版本安装详细教程
2020/04/08 Python
python Scrapy框架原理解析
2021/01/04 Python
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
如何执行一个shell程序
2012/11/23 面试题
材料物理专业大学毕业生求职信
2013/10/15 职场文书
网络专业学生个人的自我评价
2013/12/16 职场文书
大学生怎样写好自荐信
2014/02/25 职场文书
群众路线自查报告及整改措施
2014/11/04 职场文书
电影雨中的树观后感
2015/06/15 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书