回復「書籍」即可獲贈Python從入門到進階共10本電子書
前言上次兩篇基本學完的Django ORM各種操作,怎麼查,各種查。感興趣的小夥伴可以戳這兩篇文章學習下,一篇文章帶你了解Django ORM操作(進階篇)、一篇文章帶你了解Django ORM操作(基礎篇)。
但是還是遺留了一些技能。,再來瞅瞅吧!
查詢聚合操作聚合操作,不要被名字嚇到了,通常用在篩選完一些數據之後,求一下平均值了,什麼的。
例如:求所有書的總價格和平均價格
原生sql
SELECT SUM(price) AS "所有書總價格", avg(price) AS "所有書平均價格"FROMweb_book;執行結果
ORM
price = models.Book.objects.all().aggregate(Sum("price"),Avg("price"), )print(price)執行結果
可以發現和上面是一樣的,但是會發現列名是默認是欄位__聚合函數名。
原生sql是可以指定顯示的列名的,同樣,ORM也可以。
代碼
from django.db.models import Avg,Sum
price = models.Book.objects.all().aggregate(所有書總價格=Sum("price"), 所有書平均價格=Avg("price"), )print(price)執行結果
注:price的類型直接就是dict,所以,在這是不能查看原生sql的。
但是上述ORM對應的原生SQL確實如上,所以那樣理解就行了。
分組操作分組操作,就是將某一列,相同的值進行壓縮,然後就可以得出壓縮值的數量。
如果壓縮的是外鍵,還可以取出外鍵的詳細信息。
示例:查詢出每個出版社出版的數量。
通過研究表結構發現,每出版的書,都在book表中記錄,並且每本書會外鍵一個出版社id。
如果我們能對出版社id進行壓縮,然後再求出壓縮出版社id裡面對應的數量。
嘖嘖,這不就出來了嗎?
代碼
from django.db.models import Count
ret = models.Book.objects.values("publish_id").annotate(publish_count=Count("publish_id"))print(ret)執行結果
原生sql
SELECT `web_book`.`publish_id`, COUNT(`web_book`.`publish_id`) AS `publish_count`FROM `web_book`GROUP BY `web_book`.`publish_id`;ORM分組和原生SQL對應圖
這一塊,我記得當初我迷茫了一段時間,主要是不知道如何和原生SQL對應上,根據多次測試經驗,對應圖如下。
分組獲取外鍵欄位信息上述確實可以通過分組實現了功能。
但是上述只能獲取出版社id,並不能獲取出版社名啥的,但是如何獲取壓縮外鍵欄位詳細信息呢?
代碼
ret = models.Book.objects.values("publish_id").annotate(publish_count=Count("publish_id")).values("publish__title","publish__phone","publish_count")print(ret)執行結果
注:分組(annotate)後面跟的values。
裡面只能寫外鍵欄位的列和annotate裡面的列,不能寫其他。
如果分組分的不是外鍵欄位,那就不能再跟values!
分組再篩選分組再篩選本質就是原生sql的group by .. having,將壓縮完的數據在進行條件判斷。
但是對壓縮的數據進行判斷只能通過having。
示例:查詢出版社出版的書大於2本的數據。
代碼
ret = models.Book.objects.values("publish_id") \ .annotate(publish_count=Count("publish_id")) \ .filter(publish_count__gt=2)print(ret)執行結果
F查詢有時候,我們可能有這樣的需求,就是兩個列之間進行比較。
比如經典問題,一個商品,找到收藏數大於銷量的商品等之類的兩列進行比較的需求。
示例:查詢book表,評論數小於收藏數的數據。
代碼
from django.db.models import F
book = models.Book.objects.filter(comment_num__lt=F("collect_num"))print(book)實際結果
執行結果
F對象還支持加減乘除後的比較示例:評論數小於兩倍收藏數的數據。
代碼
可是*,也可以是-,+,÷
from django.db.models import F
book = models.Book.objects.filter(comment_num__lt=F("collect_num")*2)print(book)執行結果
F對象還適用於更新代碼
models.Book.objects.all().update(price=F("price")+30)Q查詢通常情況下,我們使用的filter(條件1,條件2,...),執行的都是and查詢。
但是通常一些時候,我們需要執行or查詢。
比如book表,查詢title=<<大明帝國>> or title=<<安史之亂>>的。
這時候,如果使用Django ORM,就只能使用Q查詢構建條件。
代碼
from django.db.models import Q
books = models.Book.objects.filter(Q(title="<<大明帝國>>") | Q(title="<<安史之亂>>"))print(books)執行結果
注:|是or的意思,&是and的意思。
所以,如果將上述的|換成&,filter(條件1,條件2,...)一個意思,還是and。
Q查詢之~~相當於not。
示例:查詢title = "<<大明帝國>>" or title != "<<安史之亂>>"。
代碼
from django.db.models import Q
books = models.Book.objects.filter(Q(title="<<大明帝國>>") | ~Q(title="<<安史之亂>>"))print(books)執行結果
Q查詢和and混合查詢Q查詢和and查詢同時出現,Q查詢必須在其他查詢之前。
示例:查詢title = "<<大明帝國>>" or title != "<<安史之亂>>" 並且publish_id=1的。
代碼
from django.db.models import Q
books = models.Book.objects.filter(Q(title="<<大明帝國>>") | ~Q(title="<<安史之亂>>"),publish_id=1)print(books)執行結果
動態構造Q查詢一些時候,我們可能並不太確定有什麼條件。
可能是動態傳的,傳過來多少,就拼接多少。
Q查詢,就能做到這個,在做動態Q查詢時,動態Q不僅支持or,還支持and。
示例:查詢publish_id=1或者title模糊=大明 的書。
代碼
q = Q()q.connector = "or" q.children.append(("publish_id", "1"))q.children.append(("title__contains", "大明"))
books = models.Book.objects.filter(q)print(books)執行結果
增上面說了那麼多,終於算是大概說完了,來簡單看一下怎麼添加一條數據吧。
示例:添加一本書
代碼
更新注:update只能跟在在filter之後。
示例:將title="<<大明帝國>>"的數據修改為title="<<大明帝國666>>"。
代碼
models.Book.objects.filter(title="<<大明帝國>>").update(title="<<大明帝國666>>")filter可能篩選到的是多個值,一定要注意
刪除delete只能跟在filter之後。
示例:刪除title=<<大明帝國666>>的數據。
models.Book.objects.filter(title="<<大明帝國666>>").delete()總結好了各位,到此為止,基本上,Django ORM操作基本完畢,至少80%的知識都覆蓋完畢。
本篇主要補充的是一些高端操作,例如聚合操作,分組操作,分組再篩選操作,F查詢和Q查詢。
如何動態構造Q查詢。
相對來說,Django還是自由度比價高的,而且寫起來確實比較省心。
如果在操作過程中有任何問題,記得下面留言,我們看到會第一時間解決問題。
用微笑告訴別人,今天的我比昨天強,今後也一樣。
我是碼農星期八,如果覺得還不錯,記得動手點讚一下哈。感謝你的觀看。
如果你覺得文章還可以,記得點讚留言支持我們哈。感謝你的閱讀,有問題請記得在下方留言噢~
想學習更多關於Python的知識,可以參考學習網址:http://pdcfighting.com/,點擊閱讀原文,可以直達噢~
------------------- End -------------------
往期精彩文章推薦:
歡迎大家點讚,留言,轉發,轉載,感謝大家的相伴與支持
想加入Python學習群請在後臺回復【入群】
萬水千山總是情,點個【在看】行不行
/今日留言主題/
隨便說一兩句吧~~