<h1 id="django-系列博客十二">Django 系列博客(十二)
<h2 id="前言">前言
本篇博客继续介绍 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,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'),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('bookprice')).filter(sgt=26).values('name','s')
<pre class="python"># 查询各个作者出的书的总价格
s相当于给求和结果取名字,在vlaues取值中,可以引用
ret = Author.objects.all().annotate(s=Sum('price')).values('name','s')
print(ret)
<pre class="python"># 统计不止一个作者的图书
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)
<h2 id="f-查询">F 查询
<h3 id="什么是-f-查询">什么是 F 查询
等价于
ret=Author.objects.all().annotate(s=Sum('bookprice')).filter(sgt=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()的实例,可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
from django.db.models import F
fliter(commit_num_gt=F('read_num'))
# 查询评论数大于阅读数的书
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)
<h2 id="q-查询">Q 查询
<h3 id="什么是-q-查询">什么是 Q 查询
# 查询评论数大于阅读数的书 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)
<h2 id="q-查询">Q 查询
<h3 id="什么是-q-查询">什么是 Q 查询
对两个字段的值进行或、与、非运算,不能直接运算,需要用 Q()的实例。
# 且 -----> &
# 或 -----> |
# 非 -----> ~
from django.db.models import Q
fliter(Q(name='tom')|Q(name='tony'))
# 查询不是tom写的书的名字
ret = models.Book.objects.filter(~Q(authors__name='tom')).values('name')
查询作者名字是tom或者名字是tony的书
ret = models.Book.objects.filter(Q(authorsname='tom')|Q(authorsname='tony')).values('name')
<h2 id="补充">补充:
# 查询不是tom写的书的名字 ret = models.Book.objects.filter(~Q(authors__name='tom')).values('name')查询作者名字是tom或者名字是tony的书
ret = models.Book.objects.filter(Q(authorsname='tom')|Q(authorsname='tony')).values('name')
<h2 id="补充">补充:
在实际开发中,外键通常不用:
- 约束性太强
- 查询效率低
可以通过
db_constraint=False
来取消外键约束,在 orm 创建表的时候,外键的约束不会存在,但是这样会产生脏数据。建外键约束,包括 unique 都是为了不产生脏数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。