1. 程式人生 > >Django之ORM查詢進階

Django之ORM查詢進階

values ephone lis 兩個 很多 order port splay npr

基於雙下劃線的雙表查詢

分組與聚合函數

基於雙下劃線的雙表查詢

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查詢進階