Django之ORM查詢進階
基於雙下劃線的雙表查詢
分組與聚合函數
基於雙下劃線的雙表查詢
Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關系,它能自動確認 SQL JOIN 聯系。要做跨關系查詢,就使用兩個下劃線來鏈接模型(model)間關聯字段的名稱,直到最終鏈接到你想要的 model 為止。
# 練習1: 查詢人民出版社出版過的所有書籍的名字與價格(一對多) # 正向查詢 按字段:publish queryResult=Book.objects .filter(publish__name="人民出版社") .values_list(代碼"title","price") # 反向查詢 按表名:book queryResult=Publish.objects .filter(name="人民出版社") .values_list("book__title","book__price") # 練習2: 查詢egon出過的所有書籍的名字(多對多) # 正向查詢 按字段:authors: queryResult=Book.objects .filter(authors__name="yuan") .values_list("title") # 反向查詢 按表名:book queryResult=Author.objects .filter(name="yuan") .values_list("book__title","book__price") # 練習3: 查詢人民出版社出版過的所有書籍的名字以及作者的姓名 # 正向查詢 queryResult=Book.objects .filter(publish__name="人民出版社") .values_list("title","authors__name") # 反向查詢 queryResult=Publish.objects .filter(name="人民出版社") .values_list("book__title","book__authors__age","book__authors__name") # 練習4: 手機號以151開頭的作者出版過的所有書籍名稱以及出版社名稱 queryResult=Book.objects .filter(authors__authorDetail__telephone__regex="151") .values_list("title","publish__name")
註意:
反向查詢時,如果定義了related_name ,則用related_name替換表名,例如: publish = ForeignKey(Blog, related_name=‘bookList‘):
# 練習1: 查詢人民出版社出版過的所有書籍的名字與價格(一對多) # 反向查詢 不再按表名:book,而是related_name:bookList queryResult=Publish.objects .filter(name="人民出版社") .values_list("bookList__title","bookList__price")代碼
註意: 雙下劃線的跨表查詢 不用__set了
聚合查詢與分組查詢
聚合:aggregate(*args, **kwargs)
:aggregate(*args, **kwargs) 1 2 3 4 # 計算所有圖書的平均價格 >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg(‘price‘)) {‘price__avg‘: 34.35}View Code
aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的標識符,值是計算出來的聚合值。鍵的名稱是按照字段和聚合函數的名稱自動生成出來的。如果你想要為聚合值指定一個名稱,可以向聚合子句提供它。
>>> Book.objects.aggregate(average_price=Avg(‘price‘)) {‘average_price‘: 34.35}View Code
如果你希望生成不止一個聚合,你可以向aggregate()子句中添加另一個參數。所以,如果你也想知道所有圖書價格的最大值和最小值,可以這樣查詢:
>>> from django.db.models import Avg, Max, Min >>> Book.objects.aggregate(Avg(‘price‘), Max(‘price‘), Min(‘price‘)) {‘price__avg‘: 34.35, ‘price__max‘: Decimal(‘81.20‘), ‘price__min‘: Decimal(‘12.99‘)}#Decimal數據格式
分組:annotate()
為QuerySet中每一個對象都生成一個獨立的匯總值。
(1) 練習:統計每一本書的作者個數
#查詢每一本書的作者個數 # ret= models.Book.objects.all().annotate(c=Count("authorlist__name")) # print(ret)#Queryset對象View Code
(2)每一個出版社出版過的最便宜的書:
cc=models.Publish.objects.all().annotate(s=Min("book__price"))#如果是跨表查詢就用表明__加id for i in cc: print(i.s)View Code
annotate的返回值是querySet,如果不想遍歷對象,可以用上valuelist:
queryResult= Publish.objects .annotate(MinPrice=Min("book__price")) .values_list("name","MinPrice") print(queryResult)
方式2:
queryResult=Book.objects.values("publish__name").annotate(MinPrice=Min(‘price‘))
註意:values內的字段即group by的字段
(3) 統計每一本以py開頭的書籍的作者個數:
queryResult=Book.objects .filter(title__startswith="Py") .annotate(num_authors=Count(‘authors‘))
(4) 統計不止一個作者的圖書:
queryResult=Book.objects .annotate(num_authors=Count(‘authors‘)) .filter(num_authors__gt=1)
(5) 根據一本圖書作者數量的多少對查詢集 QuerySet進行排序:
Book.objects.annotate(num_authors=Count(‘authors‘)).order_by(‘num_authors‘)
(6) 查詢各個作者出的書的總價格:
# 按author表的所有字段 group by queryResult=Author.objects .annotate(SumPrice=Sum("book__price"))#跳轉到另一個表裏 .values_list("name","SumPrice") print(queryResult) #按authors__name group by queryResult2=Book.objects.values("authors__name") .annotate(SumPrice=Sum("price")) .values_list("authors__name","SumPrice") print(queryResult2)
註意:很多代碼沒有加models
Django之ORM查詢進階