分组查询
生成多表的准备工作已经在博客[Django-ORM模型层语法(四)之多表操作准备工作]中写了,各位可以点击下方的链接,跟着操作:
app01_author表 :
id | name | age | author_detail_id |
---|---|---|---|
1 | Kevin | 18 | 1 |
2 | Steven | 20 | 2 |
3 | Adam | 28 | 3 |
app01_book表 :
id | title | price | publish_date | publishs_id |
---|---|---|---|---|
1 | 红楼梦 | 66 | 2020-02-02 | 2 |
2 | 聊斋 | 100 | 2020-02-02 | 1 |
3 | 论语 | 200 | 2020-02-02 | 2 |
4 | 三国演义 | 300 | 2020-02-02 | 1 |
5 | 老子 | 400 | 2020-02-02 | 2 |
app01_authordetail表 :
| id |phone|addr|
|–|–|–|–|
| 1 |100| 南京|
| 2 |200| 北京|
| 3 |300| 深圳|
app01_pulish表 :
id | name | addr | |
---|---|---|---|
1 | 东方出版社 | 东方 | 123@qq.com |
2 | 西方出版社 | 西方 | 666@qq.com |
app01_book_authors表 :
| id |book_id|author_id|
|–|–|–|–|
| 1 |1| 1|
| 2 |1| 2|
| 3 |2| 1|
| 4 |2| 3|
| 5|3| 1|
| 6|3| 2|
| 7|3| 3|
app01/tests.py
"""
当你只是想测试django中的某一个py文件内容 那么你可以不用书写前后端交互的形式
而是直接写一个测试脚本即可
脚本代码无论是写在应用下的tests.py还是自己单独开设py文件都可以
"""
# 测试环境的准备 去manage.py中拷贝前四行代码 然后自己写两行
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm1.settings")
import django
django.setup()
# 在这个代码块的下面就可以测试django里面的单个py文件了
# 所有的代码都必须等待环境准备完毕之后书写
from app01 import models
# 分组查询 annotate
'''
MySQL分组查询都有哪些特点
分组之后默认只能获取到分组的依据,组内其他字段都无法直接获取了
严格模式:ONLY_FULL_GROUP_BY
'''
from django.db.models import Max, Min, Sum, Count, Avg
# 1.统计每一本书的作者个数
res = models.Book.objects.annotate() # models后面点什么,就按什么分组
res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
'''
author_num是我们自己的定义的字段,用来存储统计出来的每本书对应的作者个数
'''
res = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
print(res)
# 2.统计每个出版社卖的最便宜的书的价格
res = models.Pulish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
print(res)
# 3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
'''
只要orm语句得出的结果还是一个queryset对象
那么它就还可以继续无限制地点queryset对象封装的方法
'''
print(res)
# 4.查询每个作者出的书的总价格
res = models.Author.objects.annotate(total_price=Sum('book__price')).values('name','total_price')
print(res)
'''
如果机器上出现分组查询报错的情况,需要修改数据库严格模式.
'''