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模块顶层运行的代码引起的一个Bug
Jul 04 Python
使用C语言扩展Python程序的简单入门指引
Apr 14 Python
Python二叉搜索树与双向链表转换实现方法
Apr 29 Python
python实现上传下载文件功能
Nov 19 Python
Python实现的多叉树寻找最短路径算法示例
Jul 30 Python
python Selenium实现付费音乐批量下载的实现方法
Jan 24 Python
Python中psutil的介绍与用法
May 02 Python
Python使用get_text()方法从大段html中提取文本的实例
Aug 27 Python
Python 日志logging模块用法简单示例
Oct 18 Python
python双端队列原理、实现与使用方法分析
Nov 27 Python
基于YUV 数据格式详解及python实现方式
Dec 09 Python
PySide2出现“ImportError: DLL load failed: 找不到指定的模块”的问题及解决方法
Jun 10 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
《猛禽小队》:DC宇宙的又一超级大烂片
2020/04/09 欧美动漫
PHP函数分享之curl方式取得数据、模拟登陆、POST数据
2014/06/04 PHP
PHP连接MSSQL方法汇总
2016/02/05 PHP
使用PHP免费发送定时短信的实例
2016/10/24 PHP
apache集成php7.3.5的详细步骤
2019/06/20 PHP
JavaScript 实现模态对话框 源代码大全
2009/05/02 Javascript
javascript让setInteval里的函数参数中的this指向特定的对象
2010/01/31 Javascript
js 页面关闭前的出现提示的实现代码
2011/05/25 Javascript
js Form.elements[i]的使用实例
2011/11/13 Javascript
Javascript模块化编程(三)require.js的用法及功能介绍
2013/01/17 Javascript
javascript验证上传文件的类型限制必须为某些格式
2013/11/14 Javascript
js取float型小数点后两位数的方法
2014/01/18 Javascript
教你如何使用node.js制作代理服务器
2014/11/26 Javascript
javascript运算符——逻辑运算符全面解析
2016/06/27 Javascript
详解jQuery中的DOM操作
2016/12/23 Javascript
JavaScript错误处理和堆栈追踪详解
2017/04/18 Javascript
vue-cli webpack 开发环境跨域详解
2017/05/18 Javascript
基于vue 实现token验证的实例代码
2017/12/14 Javascript
javascript trie前缀树的示例
2018/01/29 Javascript
Layui 动态禁止select下拉的例子
2019/09/03 Javascript
微信小程序swiper左右扩展各显示一半代码实例
2019/12/05 Javascript
[01:55]TI9显影之尘系列 - Evil Geniuses
2019/08/22 DOTA
30分钟搭建Python的Flask框架并在上面编写第一个应用
2015/03/30 Python
Python3处理文件中每个词的方法
2015/05/22 Python
Python计算库numpy进行方差/标准方差/样本标准方差/协方差的计算
2018/12/28 Python
Python多图片合并PDF的方法
2019/01/03 Python
详解python中的index函数用法
2019/08/06 Python
Python 实现递归法解决迷宫问题的示例代码
2020/01/12 Python
python/golang 删除链表中的元素
2020/09/14 Python
浅谈HTML5新增和废弃的标签
2019/04/28 HTML / CSS
学生出入校管理制度
2014/01/16 职场文书
优秀民警事迹材料
2014/01/29 职场文书
幼师自我鉴定
2014/02/01 职场文书
感谢信怎么写
2015/01/21 职场文书
博士论文答辩开场白
2015/06/01 职场文书
用python批量解压带密码的压缩包
2021/05/31 Python