Django版本:
>>> django.VERSION (4, 1, 0, 'final', 0)
PS:基于前几章的进度进行修改
一、聚合查询—aggregate()
聚合查询函数是对一组值执行计算,并且返回单个值
Django使用聚合查询之前需要先从django.db.models引入Avg,Max,Min,Count,Sum,注意需要首字母大写
from django.db.models import Avg,Max,Min,Count,Sum
Avg:计算平均值
Max:最大值
Min:最小值
Count:统计出现的次数
Sum:和
聚合查询返回的值的数据类型是字典,而聚合函数aggregate()是QuerySet的一个终止子句,生成的一个汇总值,相当于count()函数。需要注意的是,使用aggregate()后,数据类型就变成了字典类型,不能再使用QuerySet数据类型的一些API了
日期数据类型DateField可以使用Max和Min
返回的字典中,键的名称默认是属性名称+__聚合函数名称,值是计算出来的聚合值,如果要自定义返回字典的键的名称,可以起别名,例如:
aggregate(别名 = 聚合函数名("属性名称"))
- 实例,计算所有图书的平均价格
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models from django.db.models import Avg,Max,Min,Count,Sum def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") res = models.Book.objects.aggregate(Avg("price")) print(res,type(res)) return HttpResponse("ok")
访问127.0.0.1:8000/add_book进行测试,观察终端输出,可以看到输出数据类型是字典
- 计算所有图书的数量,价格的最大值和最小值
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models from django.db.models import Avg,Max,Min,Count,Sum def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") res = models.Book.objects.aggregate(c=Count("id"),max=Max("price"),min=Min("price")) print(res,type(res)) return HttpResponse("ok")
- 访问测试,查看终端输出
二、分组查询—annotate()
- 分组查询同样也会用到聚合函数,同样先从
django.db.models
引入Avg,Max,Min,Count,Sum
,注意需要首字母大写
from django.db.models import Avg,Max,Min,Count,Sum
- 返回值:
分组后使用
values
取值,返回值是QuerySet数据类型里面的一个个字典如果使用
Values_list
取值,那么返回值则是QuerySet数据类型里的一个个元组
- Mysql中的
limit
就相当于ORM中QuerySet数据类型的切片 - 注意:
annotate里面存放聚合函数,其中:
values或values_list放在annotate前面:前面的values或values_list声明以什么字段分组,是字典还是元组,而annotate执行分组
values或values_list放在annotate后面:annotate表示直接以当前表的pk(主键)执行分组,后面的values或values_list表示查询哪些字段,==(也就是输出什么字段)==并且要将annotate里面的聚合函数起别名,在values或values_list中写它的别名
准备数据和创建模型
- models.py # -*- coding: utf-8 -*- from django.db import models class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) pub_date = models.DateField() publish = models.ForeignKey("Publish",on_delete=models.CASCADE) #多对一 authors = models.ManyToManyField("Author") #多对多 class Publish(models.Model): name = models.CharField(max_length=32) city = models.CharField(max_length=64) email = models.EmailField() class Author(models.Model): name = models.CharField(max_length=32) age = models.SmallIntegerField() au_detail = models.OneToOneField("AuthorDetail",on_delete=models.CASCADE) #一对一 class AuthorDetail(models.Model): gender_choices = ( (0,"女"), (1,"男"), (2,"保密"), ) gender = models.SmallIntegerField(choices=gender_choices) tel = models.CharField(max_length=32) addr = models.CharField(max_length=64) birthday = models.DateField() class Emp(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() salary = models.DecimalField(max_digits=8, decimal_places=2) dep = models.CharField(max_length=32) province = models.CharField(max_length=32) class Emps(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() salary = models.DecimalField(max_digits=8, decimal_places=2) dep = models.ForeignKey("Dep", on_delete=models.CASCADE) province = models.CharField(max_length=32) class Dep(models.Model): title = models.CharField(max_length=32)
更新数据表
(test) PS F:\django\app1> python .\manage.py makemigrations app1_model Migrations for 'app1_model': app1_model\migrations\0003_dep_emp_emps_remove_book_authors_remove_book_publish_and_more.py - Create model Dep - Create model Emp - Create model Emps - Remove field authors from book - Remove field publish from book - Delete model Author - Delete model AuthorDetail - Delete model Book - Delete model Publish (test) PS F:\django\app1> python .\manage.py migrate app1_model Operations to perform: Apply all migrations: app1_model Running migrations: Applying app1_model.0003_dep_emp_emps_remove_book_authors_remove_book_publish_and_more... OK
- 查看数据库,确认之前的表删除,刚刚新的表创建
- 新建查询,写入
INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('1','令狐冲','24','6000.00','销售部','河南'); INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('2','任盈盈','18','8000.00','关公部','广东'); INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('3','任我行','56','10000.00','销售部','广东'); INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('4','岳灵珊','19','6000.00','关公部','河南'); INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('5','小龙女','20','8000.00','关公部','河北'); INSERT INTO app1_model_dep (id,title) VALUES ('1','销售部'); INSERT INTO app1_model_dep (id,title) VALUES ('2','关公部'); INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('2','令狐冲','24','8000.00','河南','1'); INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('3','任盈盈','18','9000.00','广东','2'); INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('4','任我行','57','10000.00','广东','1'); INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('5','岳灵珊','19','6000.00','河南','2'); INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('6','小龙女','20','8000.00','河北','2');
- 查看数据库信息
- 下面统计每一个出版社的最便宜的书的价格
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models from django.db.models import Avg,Max,Min,Count,Sum def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") res = models.Publish.objects.values("name").annotate(in_price = Min("book__price")) print(res) return HttpResponse("ok")
- 访问测试,查看终端输出
统计每一本书的作者个数
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models from django.db.models import Avg,Max,Min,Count,Sum def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") res = models.Book.objects.annotate(c = Count("authors__name")).values("title","c") print(res) return HttpResponse("ok")
访问测试,查看终端输出