文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Django 系列博客(十二)

2023-01-30 23:28

关注

前言

本篇博客继续介绍 Django 中的查询,分别为聚合查询和分组查询,以及 F 和 Q 查询。

聚合查询

语法:aggregate(*args, **kwargs)

# 计算所有图书的平均价格
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price'))

aggregate()是 QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值得标识符,值是计算出来的聚合值。建的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定个名称,可以向聚合子句提供它。

Book.objects.aggregate(average_price=Avg('price'))

如果你希望生成不止一个聚合值,你可以向 aggregate()子句中添加另一个参数。所以如果想知道所有图书价格的最大值和最小值,可以这样查询:

from django.db.models import Avg, Max, Min
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))

具体例子:

# 查询所有书籍的平均价格
from django.db.models import Avg,Count,Max,Min
ret=Book.objects.all().aggregate(Avg('price'))
# {'price__avg': 202.896}
# 可以改名字
ret=Book.objects.all().aggregate(avg_price=Avg('price'))
# 统计平均价格和最大价格
ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))
# 统计最小价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))
# 统计个数和平均价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))
print(ret)

分组查询

总结:

group by 那个表就以那个表作为基表
values 在前:表示 group by
values 在后:表示取值
filter 在前:表示 where 条件
filter 在后:表示 having

分组查询案例

# 查询所有作者写的书的总价格大于26的
# filter()在annotate后面,表示对分组后的结果进行筛选,相当于having
# annotate前的values()表示按该字段分组,相当于group by,可以省略,默认会按Author的id分组
# 后面的values()表示取值
ret=Author.objects.all().values('pk').annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s')

等价于

ret=Author.objects.all().annotate(s=Sum('book__price')).filter(s__gt=26).values('name','s')
# 查询各个作者出的书的总价格
# s相当于给求和结果取名字,在vlaues取值中,可以引用
ret = Author.objects.all().annotate(s=Sum('price')).values('name','s')
print(ret)
# 统计不止一个作者的图书
ret=Book.objects.all().values('pk').annotate(c=Count('authors')).filter(c__gt=1).values('name','c')
print(ret)

等价于

ret = Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
print(ret)

F 查询

什么是 F 查询

如果要对两个字段的值作比较,就不能直接比较,必须借助 F()的实例,可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

语法

from django.db.models import F
fliter(commit_num_gt=F('read_num'))

F 查询的使用

# 查询评论数大于阅读数的书
book = models.Book.objects.filter(commit_num__gt=F('read_num')).values('name')

# 把所有书的评论数加1
models.Book.objects.all().update(commit_num=F('commit_num')+1)

Q 查询

什么是 Q 查询

对两个字段的值进行或、与、非运算,不能直接运算,需要用 Q()的实例。

语法

# 且  ----->  &
# 或  ----->  |
# 非  ----->  ~
from django.db.models import Q
fliter(Q(name='tom')|Q(name='tony'))

Q 查询的使用

# 查询不是tom写的书的名字
ret = models.Book.objects.filter(~Q(authors__name='tom')).values('name')

# 查询作者名字是tom或者名字是tony的书
ret = models.Book.objects.filter(Q(authors__name='tom')|Q(authors__name='tony')).values('name')

补充:

在实际开发中,外键通常不用:

  • 约束性太强
  • 查询效率低
  • 可以通过db_constraint=False来取消外键约束,在 orm 创建表的时候,外键的约束不会存在,但是这样会产生脏数据。

  • 建外键约束,包括 unique 都是为了不产生脏数据。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯