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 Web框架Flask中使用七牛云存储实例
Feb 08 Python
详解Python中break语句的用法
May 14 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
Jun 14 Python
Python3多进程 multiprocessing 模块实例详解
Jun 11 Python
python用BeautifulSoup库简单爬虫实例分析
Jul 30 Python
python 控制Asterisk AMI接口外呼电话的例子
Aug 08 Python
python实现广度优先搜索过程解析
Oct 19 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
Jan 04 Python
tensorflow -gpu安装方法(不用自己装cuda,cdnn)
Jan 20 Python
使用python实现多维数据降维操作
Feb 24 Python
python 如何快速复制序列
Sep 07 Python
解决pytorch 模型复制的一些问题
Mar 03 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实现让页面只能被百度gogole蜘蛛访问的方法
2009/12/29 PHP
tp5(thinkPHP5框架)使用DB实现批量删除功能示例
2019/05/28 PHP
Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
2020/04/14 PHP
浅析showModalDialog数据缓存问题(用禁止浏览器缓存解决)
2013/07/09 Javascript
通过$(this)使用jQuery包装后的方法或属性
2014/05/18 Javascript
JavaScript实现把数字转换成中文
2015/06/29 Javascript
JavaScript的MVVM库Vue.js入门学习笔记
2016/05/03 Javascript
JS组件Bootstrap按钮组与下拉按钮详解
2016/05/10 Javascript
NPM 安装cordova时警告:npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to
2016/12/20 Javascript
js实现移动端导航点击自动滑动效果
2017/07/18 Javascript
vue引入jq插件的实例讲解
2017/09/12 Javascript
微信小程序模板和模块化用法实例分析
2017/11/28 Javascript
Vue 项目代理设置的优化
2018/04/17 Javascript
微信开发之微信jssdk录音功能开发示例
2018/10/22 Javascript
JS实现li标签的删除
2019/04/12 Javascript
3分钟读懂移动端rem使用方法(推荐)
2019/05/06 Javascript
vue使用swiper.js重叠轮播组建样式
2019/11/14 Javascript
用vue.js组件模拟v-model指令实例方法
2019/07/05 Python
Django 数据库同步操作技巧详解
2019/07/19 Python
python tkinter实现彩球碰撞屏保
2019/07/30 Python
使用TensorFlow对图像进行随机旋转的实现示例
2020/01/20 Python
TensorFlow:将ckpt文件固化成pb文件教程
2020/02/11 Python
Django 设置多环境配置文件载入问题
2020/02/25 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
高中数学教师求职信
2013/10/30 职场文书
万年牢教学反思
2014/02/15 职场文书
《蒙娜丽莎之约》教学反思
2014/02/27 职场文书
继承公证书样本
2014/04/04 职场文书
会计求职信
2014/05/29 职场文书
2014年秋季开学典礼致辞
2014/08/02 职场文书
售后客服个人自我评价
2014/09/14 职场文书
市场调研项目授权委托书范本
2014/10/04 职场文书
营业用房租赁协议书
2014/11/26 职场文书
撤诉申请怎么写
2015/05/19 职场文书
最美乡村教师观后感
2015/06/11 职场文书
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js