Django 系列博客(十二) 前言 本篇博客繼續介紹 Django 中的查詢,分別為聚合查詢和分組查詢,以及 F 和 Q 查詢。 聚合查詢 語法: aggregate()是 QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值得標識符,值是計算出來的聚合值。 ...
Django 系列博客(十二)
前言
本篇博客繼續介紹 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 都是為了不產生臟數據。