Django Aggregation聚合 django orm 求平均、去重、总和等常用方法
Django Aggregation聚合
在当今根据需求而不断调整而成的应用程序中,通常不仅需要能依常规的字段,如字母顺序或创建日期,来对项目进行排序,还需要按其他某种动态数据对项目进行排序。Djngo聚合就能满足这些要求。
以下面的Model为例
from django.db import models class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField() class Publisher(models.Model):
name = models.CharField(max_length=300)
num_awards = models.IntegerField() class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
pubdate = models.DateField() class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
registered_users = models.PositiveIntegerField()
快速了解
# books总数量.
>>> Book.objects.count()
2452 # Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73 # books的平均price.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35} # books的最大price.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')} # All the following queries involve traversing the Book<->Publisher
# many-to-many relationship backward # 为每个publisher添加个num_books属性,即每个pulisher出版的book的数量.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
>>> pubs[0].num_books
73 # 根据num_book属性排序.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323
聚合生成Generating aggregates over a QuerySet
Django有两种方法来生成聚合。第一种方法是为整个QuerySet生成聚合值,例如为全部的books生成price的平均值:
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}
可以简略为:
>>> Book.objects.aggregate(Avg('price'))
{'price__avg': 34.35}
函数aggregate()的参数是一系列聚合函数aggregate functions:
Avg
返回平均值
Count
class Count(field, distinct=False)
返回计数。当参数distinct=True时,返回unique的对象数目。
Max
返回最大值
Min
返回最小值.
StdDev
class StdDev(field, sample=False)
返回标准偏差
有一个参数sample
默认情况下sample=False,返回总体标准偏差,如果sample=True,返回样本标准偏差。
Sum
返回总值
Variance
class Variance(field, sample=False)
返回方差
有一个参数sample,默认返回总体方差,sample设为True时返回样本方差。
aggregate()方法被调用时,返回一个键值对字典,可以指定key的名字:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}
如果你想生成多个聚合,你只需要添加另一个参数。所以,如果我们还想知道所有书的最高和最低的价格: 计算总和 平均数据 最大值 最小值方法
>>> from django.db.models import Avg, Max, Min,Sum
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
为查询集的每个对象生成聚合值Generating aggregates for each item in a QuerySet
这是生成聚合值的第二种方法。比如你要检索每本书有多少个作者。book和author是manytomany的关系,我们可以为每本书总结出这种关系。
每个对象的总结可以用方法annotate()生成:
# 建立一个annotate QuerySet
>>> from django.db.models import Count
>>> q = Book.objects.annotate(Count('authors'))
# 第一个对象
>>> q[0]
<Book: The Definitive Guide to Django>
>>> q[0].authors__count
2
# 第二个对象
>>> q[1]
<Book: Practical Django Projects>
>>> q[1].authors__count
1
也可以指定生成属性的名字:
>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1
和aggregate()不同,annotate()的输出是一个QuerySet。
联合聚合Joins and aggregates
目前为止,我们聚合查询的field都属于我们要查询的Model,我们也可以用其它Model的field来进行聚合查询,例如:
>>> from django.db.models import Max, Min
>>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))
这样就可以查询每个Store里面books的价格范围
联合链的深度可以随心所欲:
>>> Store.objects.aggregate(youngest_age=Min('books__authors__age'))
反向关系Following relationships backwards
通过book反向查询publisher:
>>> from django.db.models import Count, Min, Sum, Avg
>>> Publisher.objects.annotate(Count('book'))
返回的QuerySet的每个publisher都会带一个属性book_count。
查询出版最久的书的出版日期:
Publisher.objects.aggregate(oldest_pubdate=Min('book__pubdate'))
查询每个作者写的书的总页数:
Author.objects.annotate(total_pages=Sum('book__pages'))
查询所有作者写的书的平均rating:
>>> Author.objects.aggregate(average_rating=Avg('book__rating'))
聚合和其它查询集操作Aggregations and other QuerySet clauses
filter() and exclude()
聚合可以和filter和exclude一起使用:
>>> from django.db.models import Count, Avg
>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors'))
>>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price'))
可以根据聚合值进行筛选:
>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)
编写一个包含annotate()和filter()从句的复杂查询时,要特别注意作用于QuerySet的从句的顺序顺序的不同,产生的意义也不同:
>>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0)
>>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))
order_by()
可以根据聚合值进行排序:
>>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
values()
通常,注解annotate是添加到每一个对象上的,一个执行了注解操作的查询集 QuerySet 所返回的结果中,每个对象都添加了一个注解值。但是,如果使用了values()从句,它就会限制结果中列的范围,对注解赋值的方法就会完全不同。就不是在原始的 QuerySet 返回结果中对每个对象中添加注解,而是根据定义在 values() 从句中的字段组合对先结果进行唯一的分组,再根据每个分组算出注解值,这个注解值是根据分组中所有的成员计算而得的:
>>> Author.objects.values('name').annotate(average_rating=Avg('book__rating'))
这样的写法下,QuerySet会根据name进行组合,返回的是每个unique name的聚合值。如果有两个作者有相同的名字,这两个作者会被当做一个计算,他们的books会合在一起。
>>>Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating')
位置互换后,会为每个author都生成一个average_rating,而且只会输出每个author的name和average_rating。
默认排序下使用聚合:
from django.db import models class Item(models.Model):
name = models.CharField(max_length=10)
data = models.IntegerField() class Meta:
ordering = ["name"]
如果你想知道每个非重复的data值出现的次数,你可能这样写:
# Warning: 不正确的写法
Item.objects.values("data").annotate(Count("id"))
这部分代码想通过使用它们公共的data值来分组Item对象,然后在每个分组中得到id值的总数。但是上面那样做是行不通的。这是因为默认排序项中的name也是一个分组项,所以这个查询会根据非重复的(data,name)进行分组,而这并不是你本来想要的结果。所以,你需要这样写来去除默认排序的影响:
Item.objects.values("data").annotate(Count("id")).order_by()
Aggregating annotations
也可以根据annotation结果生成聚合值,例如计算每本书平均有几个作者:
>>> from django.db.models import Count, Avg
>>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors'))
{'num_authors__avg': 1.66}
Django Aggregation聚合 django orm 求平均、去重、总和等常用方法的更多相关文章
- Django Aggregation聚合
在当今根据需求而不断调整而成的应用程序中,通常不仅需要能依常规的字段,如字母顺序或创建日期,来对项目进行排序,还需要按其他某种动态数据对项目进行排序.Djngo聚合就能满足这些要求. 以下面的Mode ...
- python3开发进阶-Django框架中的ORM的常用(增,删,改,查)操作
阅读目录 如何在Django终端打印SQL语句 如何在Python脚本中调用Django环境 操作方法 单表查询之神奇的下划线 ForeignKey操作 ManyToManyField 聚合查询和分组 ...
- Django之深入了解ORM
目录 Django ORM操作 常用字段 常用字段参数 自定义字段 单表操作 双下划线查询 模糊查询 多表操作 一对多字段数据的操作 多对多字段数据的操作 跨表查询 基于对象的跨表查询 基于双下划线的 ...
- 【Django】--Models 和ORM以及admin配置
Models 数据库的配置 1 django默认支持sqlite,mysql, oracle,postgresql数据库 <1>sqlite django默认使用sqlite的数据库 ...
- django中聚合aggregate和annotate GROUP BY的使用方法
接触django已经很长时间了,但是使用QuerySet查询集的方式一直比较低端,只会使用filter/Q函数/exclude等方式来查询,数据量比较小的时候还可以,但是如果数据量很大,而且查询比较复 ...
- Django框架之数据库ORM框架
首先,我来介绍一下什么是ORM框架: O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思.在ORM框架中,它帮 ...
- Django(三) ORM 数据库操作
大纲 一.DjangoORM 创建基本类型及生成数据库表结构 1.简介 2.创建数据库 表结构 二.Django ORM基本增删改查 1.表数据增删改查 2.表结构修改 三.Django ORM 字段 ...
- python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)
昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...
- {Django基础六之ORM中的锁和事务}一 锁 二 事务
Django基础六之ORM中的锁和事务 本节目录 一 锁 二 事务 一 锁 行级锁 select_for_update(nowait=False, skip_locked=False) #注意必须用在 ...
随机推荐
- android 当ListView滚动时自动调用 onCheckedChanged 导致CheckBox 状态不停变化 的解决办法
今天在做一个含有CheckBox 的ListView时,发现当初始化CheckBox的状态后, 滚动ListView,其中CheckBox 的选中状态不停的发生变化.最后发现原因是 ListView滚 ...
- IntelliJ IDEA 最新激活码(截止到2018年10月14日)
IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYX ...
- ASP.NET Core之项目文件简介及配置文件与IOC的使用
原文地址:https://www.cnblogs.com/knowledgesea/p/7079880.html 序言 在当前编程语言蓬勃发展与竞争的时期,对于我们.net从业者来说,.Net Cor ...
- MVC+Spring.NET+NHibernate .NET SSH框架整合 C# 委托异步 和 async /await 两种实现的异步 如何消除点击按钮时周围出现的白线? Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法
MVC+Spring.NET+NHibernate .NET SSH框架整合 在JAVA中,SSH框架可谓是无人不晓,就和.NET中的MVC框架一样普及.作为一个初学者,可以感受到.NET出了MV ...
- android 蓝牙编程重点---如何发送和接收16进制数据
最近的android蓝牙开发项目也逐渐接近尾声,基本的功能都已经完成,只剩下界面的设计.现在真的是舒了一口气! 作为编程学习经验只有1年的菜鸟,这是我独自完成的商业性产品,而且还是涉及到与单片机蓝牙模 ...
- 8个实用而有趣Bash命令提示行
很多人都对过命令行提示的重要性不屑一顾,甚至是一点都不关心.但是我却一点都不这么认为,一个好的命令行提示可以改变你使用命令的方式.为此,我在internet上找到一些非常实用,优秀,并有趣的bash的 ...
- IE6-IE9兼容性问题列表及解决办法:锁表头的JQuery方案和非JQuery方案(不支持IE6,7,8)
鉴于从IE8开始,IE不再支持css的expression了,所以以前依靠它完成锁表头的代码就全部失效了,面对新的浏览器,一切又要重新来过了. 现在所能找到的对于锁表头的方案主要有两种路子:一种是使用 ...
- 最强 Android Studio 使用小技巧和快捷键总结
最强 Android Studio 使用小技巧和快捷键总结 写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android ...
- js中多个数字运算后值不对(失真)处理方法
最近遇到一个bug ,在js里面计算两个数字相减,633011.20-31296.30 得到的结果居然是601714.89,领导不乐意了说怎么少了0.01,我一听,噶卵达,来达鬼,不可能啊,我Goog ...
- ARM:移动GPU往PC GPU效能迈进
行动装置的热潮持续不退,各大手机制造商除了想尽办法推出外型酷炫的行动装置设备来吸引消费者的目光之外,更在行动应用处理器玩起多核心的「核」战争,无非是希望能够带给消费者更优异的效能新体验.然而,随着消费 ...