Django开发:聚合分组F、Q查询与选择
1.聚合查询
需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg
关键语法:aggregate(alias 聚合结果 = 聚合函数(参数))
查询结果:使用聚合函数得到各组的结果:字典
注:
1 分组后必须使用聚合函数
2 没有分组,即全部默认为组
3 查询结果是正则字典
"""
聚合查询通常情况下都是配合分组一起使用的
只要是跟数据库相关的模块
基本上都在 django.db.models 里面
上述没有那么应该在 django.db里面
"""
from django.db.models import Max, Min, Sum, Count, Avg
# 1 所有书的平均价格
res = models.Book.objects.aggregate(Avg('price'))
print(res)
# 2 上述方法一次性使用
res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Count('pk'), Avg('price'))
print(res)
2.分组查询
1 关键字:注释
2 默认是根据当前表id分组,使用聚合函数在分组内进行聚合计算,得到result 作为查询结果中组中的属性
from django.db.models import Max, Min, Sum, Count, Avg
# 1 统计每一本书的作者个数
res = models.Book.objects.annotate() # models后面点什么 就是按什么分组
res1 = models.Book.objects.annotate(author_num = Count('authors')).values('title', 'author_num')
res2 = models.Book.objects.annotate(author_num = Count('authors__nid')).values('title', 'author_num')
print(res, res1, res3)
"""
author_num 自己定义的字段 用来存储统计出来的每本书对应的作者个数
"""
# 2 统计每个出版社卖的最便宜的书的价格
res = models.Publish.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')
print(res)
# 4 查询每个作者出的书的总价格
res = models.Author.objects.annotate(sum_price = Sum('book__price')).values('name', 'sum_price')
print(res)
# 5 统计 price大于150元 的书籍的作者个数
res = models.Book.objects.filter(price__gt = 150).annotate(num_authors = Count('authors')).values('title', 'num_authors')
print(res)
3. F、Q 查询
# F查询
"""
能够帮助你直接获取到表中某个字段对应的数据
"""
from django.db.models import F
# 1 将所有书籍的价格提升 10 块
models.Book.objects.update(price = F('price') + 10)
# 2 将 django 书的名称后面加上 ' web' 字
"""
在操作字符类型的数据的时候 F不能够直接做到字符串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.filter(title = "django").update(title = Concat(F('title'), Value(' web')))
# Q查询
"""
filter括号内多个参数是and关系
"""
from django.db.models import Q
# Q包裹逗号分割 还是and关系
res1 = models.Book.objects.filter(Q(price__lt = 300), Q(price__gt = 400))
print(res1)
# | or关系
res2 = models.Book.objects.filter(Q(pub_date__lt = '2020-01-01') | Q(price__gt = 300))
print(res2)
# ~ not关系
res3 = models.Book.objects.filter( ~ Q(pub_date__lt = '2020-01-01') | Q(price__lt = 200))
print(res3) # <QuerySet []>
# Q的高阶用法 能够将查询条件的左边也变成字符串的形式
# 提前生成 Q 对象,并使用 append方法 添加条件
q = Q()
q.connector = 'or'
q.children.append(('pub_date__lt', '2020-01-01'))
q.children.append(('price__lt', 200))
res = models.Book.objects.filter(q) # 默认是and关系
print(res)
确定字段,确定参数选择
2 选择作为元组的元组集合(预先定义,通常在表类中指定列之前)
3 每个元组存储两个元素形成匹配关系)对应第二个的值元组的元素。如果没有匹配关系,则返回自身
示例:
# 定义一个 UserTest 表
class UserTest(models.Model):
name = models.CharField(max_length = 64)
gender_choices = ((1, '男'),(2, '女'),(3, '其他'))
gender = models.IntegerField(choices = gender_choices)
# 同步迁移到数据库
python manage.py makemigrations
python manage.py migrate
# 在 test.py 配置测试环境
# 录入数据
models.UserTest.objects.create(name = '小微', gender = 1)
models.UserTest.objects.create(name = '小芬', gender = 2)
models.UserTest.objects.create(name = '小桃', gender = 3)
models.UserTest.objects.create(name = '小月', gender = 4)
# 验证choices
for user_obj in models.UserTest.objects.all():
print(user_obj.gender, end=' ')
print(user_obj.get_gender_display())
'''
1 男
2 女
3 其他
4 4
'''
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。