经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Django » 查看文章
django的聚合函数和aggregate、annotate方法使用详解
来源:jb51  时间:2019/7/24 8:36:16  对本文有异议

支持聚合函数的方法:

提到聚合函数,首先我们要知道的就是这些聚合函数是不能在django中单独使用的,要想在django中使用这些聚合函数,就必须把这些聚合函数放到支持他们的方法内去执行。支持聚合函数的方法有两种,分别是aggregate和annotate,这两种方法执行的原生SQL以及结果都有很大的区别,下面我们以实例操作的方式一一介绍:

  1.   # 示例模型:
  2.   class Author(models.Model):
  3.     """作者模型"""
  4.     name = models.CharField(max_length=100)
  5.     age = models.IntegerField()
  6.     email = models.EmailField()
  7.  
  8.   class Book(models.Model):
  9.     """图书模型"""
  10.     name = models.CharField(max_length=100)
  11.     author = models.ForeignKey('Author',on_delete=models.CASCADE)
  12.     price = models.FloatField()
  13.  
  14.   class BookOrder(models.Model):
  15.     """图书订单模型"""
  16.     book = models.ForeignKey('Book',on_delete=models.CASCADE)
  17.     sailprice = models.FloatField()
  18.     create_time = models.DateTimeField(auto_now_add=True)

1、aggregate:这个方法时一个QuerySet对象的API,在执行聚合函数的时候,是对QuerySet整个对象的某个属性汇总,在汇总时不会使用该模型的主键进行group by进行分组,得到的是一个结果字典。同时,该方法支持聚合关联表(如使用ForeignKey)中的字段,在聚合连表中字段时,传递该字段的方式与查询连表时传递字段的方式相同,会使用到"__"。示例代码如下:

  1.   from django.db.models import Avg
  2.   from django.db import connection

1、对当前表中数据进行聚合:

  1.   result = Author.objects.aggregate(avg_age=Avg('age'))
  2.   print(connection.queries)   # 打印执行时所有的查询语句

2、对连表中数据进行聚合:

  1.   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表中):

  1.   from django.db.models import Avg
  2.   from django.db import connection
  3.  
  4.   books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))
  5.   for book in books:
  6.   print('%s/%s'%(book.name,book.avg))   # 注意这里的avg属性就是annotate执行聚合函数得到的
  7.   print(connection.queries)

聚合函数:

在Django中,聚合函数都是在django.db.models模块下的,具体的聚合函数有Avg、Count、Max、Min、Sum,现在我们一一介绍这些函数的作用:

1、Avg:计算平均值,使用于与数值相关的字段,如果使用aggregate方法来执行这个函数,那么会得到一个字典,默认情况下,字典的键为field__avg,值为执行这个聚合函数所得到的值,示例代码如下:

  1.   # 计算所有作者的平均年龄
  2.   result = Author.objects.aggregate(Avg('age'))
  3.   print(result) # 结果为:{"age__avg": 23.8}
  4.  
  5.   # 如果想要使用自定义的键,那么可以把aggregate中的未知参数变为关键字参数,该关键字就是得到的键,示例代码如下:
  6.   result = Author.objects.aggregate(avgAge=Avg('age'))
  7.   print(result) # 结果为:{"avgAge": 23.8}
  8.  
  9.   # 如果使用annotate方法执行这个函数,那么得到的结果就是一个QuerySet对象,只不过这个对象中的每一个都会添加一个属性,这个属性的名称其实和上面的键一样,可以使用默认也可以自定义,使用方法与在aggregate中键名的定义一样,这里就不再赘述:
  10.   books = Book.objects.annotate(avg=Avg('bookorder__sailprice'))
  11.   for book in books:
  12.     print('%s/%s'%(book.name,book.avg)) # 注意这里的avg属性就是annotate执行聚合函数得到的
  13.   print(connection.queries)

2、Count:计算数量,基本用法与Avg相同,在使用这个聚合函数的时候可以传递一个distinct参数用来去重:

  1.   # 计算总共有多少个订单
  2.   result = BookOrder.objects.aggregate(total=Count('id',distanct=True))
  3.   print(result) # 结果为:{"total": 18}
  4.   # 计算每本书的订单量
  5.   books = Book.objects.annotate(total=Count('bookorder__id'))
  6.   for book in books:
  7.   print('%s/%s'%(book.name,book.total))

3、Max和Min:计算某个字段的最大值和最小值,用法与Avg一样

4、Sum:计算总和,用法与Avg一样

注:总结一下,其实可以简单的理解使用aggregate时,是对QuerySet整个对象的某个属性汇总聚合,不会使用分组。而使用annotate方法时,是为QuerySet中的每个对象生成一个独立的摘要,一定会使用分组,然后再聚合

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号