当前位置:首页 > 编程教程 > Python技术文章 > Django Aggregation聚合使用方法解析

Django Aggregation聚合用法实例

  • 发布时间:
  • 作者:码农之家
  • 点击:81

这篇文章主要知识点是关于django、aggregation、的内容,如果大家想对相关知识点有系统深入的学习,可以参阅以下电子书

Django开发宝典
Django开发宝典全书高清版
  • 类型:Django大小:85.5 MB格式:PDF作者:王友钊、黄静
立即下载

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
>>> 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'))

两个查询都返回了至少出版了一本好书(评分大于3分)的出版商的列表。但是第一个查询的注解包含其该出版商发行的所有图书的总数;而第二个查询的注解只包含出版过好书的出版商的所发行的好书(评分大于3分)总数。在第一个查询中,注解在过滤器之前,所以过滤器对注解没有影响。

在第二个查询中,过滤器在注解之前,所以,在计算注解值时,过滤器就限制了参与运算的对象的范围

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}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。

以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。

django 相关电子书
学习笔记
网友NO.380435

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

支持聚合函数的方法: 提到聚合函数,首先我们要知道的就是这些聚合函数是不能在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:……

网友NO.667236

django 中的聚合函数,分组函数,F 查询,Q查询

先以mysql的语句,聚合用在分组里, 对mysql中groupby 是分组 每什么的时候就要分组,如 每个小组,就按小组分, group by 字段 having 聚合函数 #举例 :求班里的平均成绩, select Avg(score) from stu 在django中 聚合 是aggreate(*args,**kwargs),通过QuerySet 进行计算。做求值运算的时候使用 分组 是annotate(*args,**kwargs),括号里是条件,遇到 每什么的时候就要分组, 先从models 导入要用到的函数 from django.db.models import Min,Avg,Max,Sumdef aggregate(request): #求所有书籍的平均价格 ret11 = Book.objects.all().aggregate(Avg("price")) # print(ret11)#{'price__avg': 51.975} #求所有书籍的最高价 ret12 = Book.objects.all().aggregate(MaxPrice=Max('price')) # print(ret12)#{'MaxPrice': Decimal('100.00')} #egon 出版过书籍的最高价格 p = Book.objects.filter(authors__name='egon').aggregate(Max('price')) print(p)#{'price__max': Decimal('100.00')} #分组 annotate() #每一个作者……

网友NO.278793

Django ORM 聚合查询和分组查询实现详解

models.py: from django.db import models # 出版社class Publisher(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=64, null=False, unique=True) def __str__(self): return "Publisher object: {}".format(self.name) # 书籍class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=64, null=False, unique=True) price = models.DecimalField(max_digits=5, decimal_places=2, default=00.00) # 最长位数为 5,小数位数为 2,默认值为 00.00 publisher = models.ForeignKey(to="Publisher", null=True) # 把 null 设置为 True def __str__(self): return "Book object: {}".format(self.title) # 作者class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16, null=False, unique=True) book = models.ManyToManyField(to="Book") # 多对多关联 Book 表,ORM 会自动生成第 3 张表 def __str__(self): return "Author object: {}".format(self.name) book 表: 修改……

<
1
>

Copyright 2018-2020 www.xz577.com 码农之家

版权投诉 / 书籍推广 / 赞助:520161757@qq.com