python day-76 django orm 查詢鏈表
一、基於雙下劃線跨表查詢(join查詢)
在上一篇中,我們簡單的介紹了基於對象的跨表查詢,本章將繼續闡述基於雙下劃線的跨表查詢,所用的表格均為上章中所創建的表格。
##########################基於雙下劃線的查詢:正向查詢,按字段,反向查詢,按表名#####################
1、一對多
實例一(正向,用字段):
# 查詢紅樓夢的出版社名稱 #方式1: ret=Book.objects.filter(title="紅樓夢").values("publish__name") print(ret) # <QuerySet [{‘publish__name‘: ‘北京出版社‘}]> # 方式2: res=Publish.objects.filter(book__title="紅樓夢").values("name") print(res) #<QuerySet [{‘name‘: ‘北京出版社‘}]>
實例二(反向,用表名):
# 查詢沙河出版社出版過的書籍名稱 #方式1: ret=Publish.objects.filter(name="沙河出版社").values("book__title") print(ret) #<QuerySet [{‘book__title‘: ‘金品梅2‘}, {‘book__title‘: ‘金品梅3‘}]> #方式2: res=Book.objects.filter(publish__name="沙河出版社").values("title") print(res) #<QuerySet [{‘title‘: ‘金品梅2‘}, {‘title‘: ‘金品梅3‘}]>
2、多對多
實例一(正向,用字段):
# 查詢紅樓夢所有作者的名字 ret=Book.objects.filter(title="紅樓夢").values("authors__name") print(ret) #<QuerySet [{‘authors__name‘: ‘alex‘}, {‘authors__name‘: ‘egon‘}]>
實例二(反向,用表名):
#查詢alex出版過的所有書籍 ret=Author.objects.filter(name="alex").values("book__title") print(ret) #<QuerySet [{‘book__title‘: ‘金品梅2‘}, {‘book__title‘: ‘紅樓夢‘}]>
3、一對一
實例一(正向,用字段):
# 查詢地址在沙河並且email是123的作者的名字 ret=AuthorDetail.objects.filter(adrr="沙河",email=123).values("author__name") print(ret) #<QuerySet [{‘author__name‘: ‘alex‘}]>
實例二(反向,用表名):
# 查詢alex作者的adrr地址 ret = Author.objects.filter(name="alex").values("authordetail__adrr") print(ret) #<QuerySet [{‘authordetail__adrr‘: ‘沙河‘}]>
實例三(綜合實例):
#email以456開頭的作者出版過的所有書籍名稱以及出版社名稱
ret=Book.objects.filter(authors__authordetail__email__startswith="456").values("title","publish__name") print(ret)
總結,在上一章的對象查詢中,我們可以總結為所有的查詢是基於一個models對象,而本節中雙下劃線查詢均是基於queryset對象進行的!反向查詢使用的表名同樣必須為小寫。
二、聚合函數(aggregate)
aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。如果你想要為聚合值指定一個名稱,可以向聚合子句提供它。如下例:
#查詢所有書籍的平均價格 # 實例1: ret=Book.objects.all().aggregate(Avg("price")) print(ret) #{‘price__avg‘: 172.66666666666666} # 實例2: res = Book.objects.all().aggregate(avgPrice=Avg("price")) print(res) #{‘avgPrice‘: 172.66666666666666}
如果你希望生成不止一個聚合,你可以向aggregate()子句中添加另一個參數。所以,如果你也想知道所有圖書價格的最大值和最小值,可以這樣查詢:
# 查詢所有書籍的平均價格、價格最大值、價格最小值 ret = Book.objects.all().aggregate(Avg("price"),Min("price"),Max("price")) print(ret) #{‘price__avg‘: 172.66666666666666, ‘price__min‘: Decimal(‘123.00‘), ‘price__max‘: Decimal(‘230.00‘)}
以上實例中需要按照如下方式引入相應的模塊方法:
from
django.db.models
import
Avg,
Max
,
Min
三、分組函數(annotate)
annotate()為調用的QuerySet中每一個對象都生成一個獨立的統計值(統計方法用聚合函數)。
實例1:查詢每一個出版社出版過的書籍個數
ret=Publish.objects.all().annotate(num=Count("book__title")) #可以理解為每一個出版社對象增加一個num字段,該字段值是通過聚合函數聯表求得 for pub_obj in ret: print(pub_obj.name,pub_obj.num)
annotate的返回值是querySet,如果不想遍歷對象,可以用上values_list,如下:
ret = Publish.objects.all().annotate(num=Count("book__title")).values_list("name","num") print(ret) #<QuerySet [(‘人民出版社‘, 0), (‘沙河出版社‘, 2), (‘北京出版社‘, 1)]>
實例2:查詢每一本書的作者個數
ret=Book.objects.all().annotate(counts=Count("authors__nid")).values("title","counts") print(ret) #<QuerySet [{‘title‘: ‘金品梅2‘, ‘counts‘: 2}, {‘title‘: ‘金品梅3‘, ‘counts‘: 2}, {‘title‘: ‘紅樓夢‘, ‘counts‘: 2}]>
python day-76 django orm 查詢鏈表