72.Python中ORM聚合函数详解:Avg,aggregate,annotate

聚合函数: 如果你用原生SQL语句,则可以使用聚合函数提取数据。比如提取某个商品销售的数量,那么就可以使用Count,如果想要知道销售的平均价格,那么就可以使用Avg。 聚合函数是通过aggregate方法来实现的,在讲解这些聚合函数的用法的时候,都是基于以下的模型来实现的。

示例代码如下:

\'\'\'python #模型要放在app当中。所以首先要在终端命令行窗口,执行命令: python manage.py startapp front 同时要将新创建的app添加到settings.py文件中的INSTALLED_APPS变量中。 同时要配置完全pycharm和数据库的连接信息。 settings.py文件中示例代码如下: DATABASES = { \'default\': { \'ENGINE\': \'django.db.backends.mysql\', \'NAME\': \'orm_aggregate_demo\', \'USER\': \'root\', \'PASSWORD\': \'root\', \'HOST\': \'127.0.0.1\', \'PORT\': \'3306\', } } models.py文件中示例代码如下: from django.db import models # 定义作者的模型 class Author(models.Model): <!-- 指定unique=True,规定字段的唯一性 --> name = models.CharField(max_length=30, unique=True) age = models.IntegerField() email = models.EmailField() class Meta: db_table = \'author\' # 定义出版社模型 class Publisher(models.Model): <!-- 指定unique=True,规定字段的唯一性 --> name = models.CharField(max_length=100, unique=True) class Meta: db_table = \'publisher\' # 定义一个图书模型 class Book(models.Model): <!-- 指定unique=True,规定字段的唯一性 --> name = models.CharField(max_length=100, unique=True) pages = models.IntegerField() price = models.FloatField() rating = models.FloatField() author = models.ForeignKey(\'Author\', on_delete=models.CASCADE) publisher = models.ForeignKey(\'Publisher\', on_delete=models.CASCADE) class Meta: db_table = \'book\' # 定义一个预定书的模型 class BookOrder(models.Model): book = models.ForeignKey(\'Book\', on_delete=models.CASCADE) price = models.FloatField() class Meta: db_table = \'book_order\' 终端命令行窗口,执行命令:python manage.py makemigrations(生成相应的迁移脚本)和python manage.py migrate(将生成的迁移脚本映射到数据库中。) 1.aggregate()方法: 1. Avg:求平均值函数,如果想要获取图书的价格平均值,那么就可以使用以下代码实现: 导入模型 from .models import Book from django.db.models import Avg from django.http import HttpResponse # views.py文件中: def index(request): # 聚合函数要放在aggregate()方法中,还有其他的能够执行聚合函数的方法,之后会进行讲解 result = Book.objects.aggregate(Avg(\'price\')) print(result)

此时打印出的输出结果就是:
{"price__avg": 价格}
“price__avg”是根据field__avg规则构成的,如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。
示例代码如下:

from django.db.models import Avg result = Book.objects.aggregate(my_avg=Avg(\'price\')) print(result)

此时打印出的输出结果就是:
{"my_avg": 价格}

同时我们可以打印出查询的原生SQL语句

from django.db import connection def inex(request): result = Book.objects.aggregate(Avg(\'price\')) print(connection.queries) # queries中存储了很多的SQL语句。 # 不能够通过print(result.query),进行打印SQL语句。 # 因为result为dict类型,没有query属性。 print(type(result)) 1.所有聚合函数都是放在\'django.db.models\'下面。 2.聚合函数不能够够单独执行,必须放在能够执行聚合函数的方法中去执行,比如“aggregate()”方法。 3.在执行聚合函数的时候,会给这个聚合函数取个名字,取名字的规则,默认是“field__聚合函数名”。如果不想使用默认的名字,可以在执行聚合函数的时候传递进去关键字参数,示例代码如下: result = Book.objects.aggregate(avg=Avg("price")) 4.如果想要查看执行查询操作的sql语句的话,就要导入connection了,因为执行aggregate()方法返回的是字典类型的值,但是如果想要调用query查看原生sql语句的话,执行调用的对象必须是QuerySet类型的对象,而字典没有query属性。但是我们可以通过django.db import connection,进而就可以调用connection.queries。示例代码如下: from django.db import connection from .models import Book from django.http import HttpResponse from django.db.models import Avg def index(request): result = Book.objects.aggregate(Avg(\'price\')) print(connection.queries) return HttpResponse("success!") 2. Count:获取指定对象的个数,示例代码如下: 导入模型 result = Book.objects.aggregate(book_num=Count(\'id\'))

此时就会返回Book表中图书的数量.

3.annotate()方法: from django.shortcuts import render from django.http import HttpResponse from .models import Author,Publisher,Book,BookOrder from django.db.models import Avg,Count,Sum from django.db import connection def index(request): # 计算同一种书的预定平均价格,使用annotate()方法执行聚合函数,可以进行分组(group by) # 由父类和子类的模型关系我们知道,子类通过外键的关系了父类,那么django就会在底层为父类添加一个名为子类名字小写形式的方法。 books = Book.objects.annotate(avg=Avg("bookorder__price")) # print(books) # 打印出结果:<QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>, <Book: Book object (4)>]> # 结果显示的是QuerySet类型,可以通过遍历得到具体的图书相关信息 for book in books: print("%s,%s,平均价格:%s" % (book.name,book.author,book.avg)) # 打印出结果: # 三国演义,罗贯中,47,312587329@qq.com,平均价格:101.5 # 水浒传,施耐庵,57,1924572@qq.com,平均价格:107.5 # 红楼梦,曹雪芹,42,123521472@qq.com,平均价格:102.0 # 西游记,吴承恩,34,193452272@qq.com,平均价格:None print(connection.queries) # 打印出结果:[{\'sql\': \'SELECT @@SQL_AUTO_IS_NULL\', \'time\': \'0.000\'}, {\'sql\': \'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED\', \'time\': \'0.000\'}, {\'sql\': \'SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id`, AVG(`book_order`.`price`) AS `avg` FROM `book` LEFT OUTER JOIN `book_order` ON (`book`.`id` = `book_order`.`book_id`) GROUP BY `book`.`id` ORDER BY NULL LIMIT 21\', \'time\': \'0.000\'}] return HttpResponse("success !") aggregate和annotate的区别: 1.aggregate:返回的是字典类型的数据,默认情况下,键名为聚合函数操作的字段名__聚合函数名,键所对应的值就是聚合函数返回的值了。但是aggregate()方法不会返回QuerySet。 2.annotate:在原来模型的基础上欠佳一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)。如果在求图书的销售总额的话,那么将在每条图书的数据上都添加一个字段叫做total,计算这本书的销售总额。而如果使用的是aggregate,那么将求出所有图书的销售总额。 其中,aggregate()方法返回的是一个字典,字典中的值就是执行聚合函数的值,而annotate()方法返回的是一个“QuerySet”对象,并且会在查找的模型上添加一个聚合函数的属性。annotate()方法会使用“group by”字句进行分组,只有调用了“group by”字句,才能对每一条数据求聚合函数的值。而aggregate()方法不能调用“group by”字句。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjjjj.html