ORM的查詢
基於對象的跨表查詢(sql裏的子查詢)(重點)
一對多查詢:
Book(有外鍵)--------------->Publish 屬於正向查詢 按book表裏的字段book.publish
Book(含外鍵)<---------------Publish 是反向查詢 按表名小寫_set.all()
正向查詢 例如:查python這本書的出版社的名字和郵箱
book=Book.objects.filter(title="python").first() #拿到對象, 對象.屬性才可以獲取值
print(book.publish.name)
print(book.publish.email)
反向查詢 例如:查蘋果出版社 出版的所有書籍的名字
pub_obj=Publish.objects.get(name="蘋果出版社")
print(pub_obj.book_set.all()) # print(pub_obj.book_set) 出版社找書, 因為出版過很多書,所以用 _set, .all()是找出所有的書
多對多查詢:
Book(有外鍵)--------------->Author 正向查詢 按book表裏的字段book.authors.all() 得到的是一個集合
Book(含外鍵)<---------------Publish 反向查詢 按表名小寫_set.all()
正向查詢 例如找python作者的年齡
book=Book.objects.filter(title="python").first() #拿到python這本書
ret = book.authors.all() # 拿到與這本書關聯的所有作者queryset
ret2 = book.authors.all().value("age")
print(ret2)
反向查詢 例如找alex出版過的書
alex=Author.objects.filter("name"="Alex").first() #獲取到alex對象 filter得到的是queryset .first()得到的是對象
print(alex.book_set.all())
一對一查詢
Author--------------->AuthorDetail 正向查詢 按字段 alex.ad(Author表裏的字段)
Author<---------------AuthorDetail 反向查詢 按表名 ad.author(表名)
正向查詢 例如:查詢alex的手機號
alex=Author.objects.filter("name"="alex").first()
print(alex.ad.tel)
反向查詢 例如:查手機號是110的用戶名
ad=AuthorDetail.objects.filter(tel=110).first()
print(ad.author.name)
-------------------------------------------------------------------------------------------------
雙下劃線的跨表查詢(基於sql中的join實現 ) (重點)
規則:正向查詢按字段 反向查詢按表名的小寫
不管以哪張表為基表, 寫在最前面的過濾條件是不變的, 變的是過濾條件的書寫方式, 就是按照上面的規則拼寫
一對多
例1: 查python的出版社的名字和郵箱
以Book為基表 從Book 往Publish方向找 是正向查詢
ret=Book.objects.filter(title="python").values("publish__name") #在values這開始跨表 告訴ORM的book表拼publish表
print(ret)
以Publish為基表 查出版python的出版社名字
ret=Publish.objects.filter(book__title="python").values("name")
#book__title="python" title不在基表Publish中 所以先拼表book(title字段在book中) 再反向拼表按表名小寫book__title
#values("name") name是基表Publish自己的字段可以直接使用
例2: 查蘋果出版社出版的所有的書的名字
以Book為基表 是正向查詢
ret=Book.objects.filter(pubish__name="蘋果出版社").values("title")
print(ret)
#蘋果出版社不在基表Book裏面,所以要先到Publish中把name="蘋果出版社"的過濾出來
#title是Book基表自己的字段
以Publish為基表 反向查詢
ret=Publish.objects.filter(name="蘋果出版社").values("book__title"")
print(ret)
#name="蘋果出版社" name在基表Pubish裏面,所以直接使用name字段
#title 不在基表Publish裏面, 所以要先找到Book表 (通過表名小寫的方式), 再__title
多對多
例1: 查python這本書作者的名字
以Book為基表 正查按字段
ret=Book.objects.filter(title="python").values("author__age")
print(ret)
#author Book拼關聯的author表 把三張表拼在一起
#title在基表Book裏面
以Author為基表
ret=Author.objects.filter(book__title="python").values("age")
print(ret)
例2: 查alex出版過的書
以Book表為基表
ret=Book.objects.filter(authors__name="alex").values("title")
print(ret) # [{ "title"=python }]
以Author表為基表
ret=Author.objects.filter(name="alex").values("book__title")
print(ret) # [{ "book__title"=python }] 對比一下兩種方式的查詢結果
一對一
例1: 查alex的tel
以Author為基表 正向查詢條件按字段
ret=Author.objects.filter(name="alex").values("ad__tel")
print(ret)
以AuthorDetail為基表
ret=AuthorDetail.objects.filter(authors__name="Alex").values("tel")
print(ret)
例2:手機號為110的作者的名字
以AuthorDetail為基表
ret=AuthorDetail.objects.filter(tel="110").values("author__name")
print(ret)
# tel在基表裏面,所以直接查詢.
# name不在基表裏面,所以要加表名小寫author__name
以Author為基表
ret=Author.objects.filter("ad__tel=110").values("name")
print(ret)
--------------------------------------------------------------------------------------------
連續跨表查詢
例1: 人民出版社出版過所有書的名稱以及作者的名字 (會用到Publish Book Author三張表)
以Publish為基表
ret=Publish.objects.filter(name="人民出版社").values("book__title","book__authors__name")
print(ret)
#name在基表的字段裏, title和name需要用所在的表名小寫連接起來再查詢
#站在基表的角度跨表
以Book為基表
ret=Book.objects.filter(publish__name="人民出版社").values("title","author__name")
print(ret)
例2: 以手機號110開頭的作者出版過的所有的 書的名稱以及出版社名稱(會用AD Author Book Publish四張表 )
以Author為基表
ret=Author.objects.filter(ad__tel__startswith=110).values("book__title","book__publish__name")
print(ret)
#沒有在基表裏的查詢字段都需要用加引號
------------------------------------------------------------------------------------------
聚合 分組查詢
from django.db.models import Avg, Sum, Max, Min, Count
聚合
例1: 查詢所有書籍的平均價
ret=Book.objects.all().aggregate(priceAvg=Avg("price"))
print(ret) #{"priceAvg":123}
例2: 查有多少本書
ret=Book.objects.all().aggreagte(c=Count("nid"))
print(ret) #{"c":4}
分組 以哪個字段分組 就把哪個字段放在values()裏
單表分組查詢
例1: 查詢Book表中每個出版社的id以及對應出版書的個數
ret=Book.objects.values("title").annotate()
#按照title分組的group by values裏面是分組的字段
例2: 求每個部門的平均工資
ret=Emp.objects.values("dep").annotate(avg_salary=Avg("salary"))
# 按部門分組 求平均工資
例3: 求每個出版社 出版的書的個數
ret=Book.objects.values("pubish__id").annotate(c=Count(1))
#publish__id是Book表裏的字段
print(ret)
#[{"publish_id":1, "c":2}, {"publish_id":2, "c":1}, {"publish_id":3, "c":1}]
跨表分組查詢 以哪個字段分組 就把哪個字段放在values()裏
例1: 查詢每個出版社名稱以及出版過的書的平均價格 查詢什麽 就以什麽為基表簡單點
ret=Publish.objects.values("nid").annotate(avg_price=Avg("book__price"))
# book__price拼表 按Publish表的nid分組
例2: 查詢每一個作者的名字以及出版過的書的最高價 查詢什麽 就以什麽為基表簡單點
ret=Author.objects.values("name").annotate(maxPrice=Max("book__price"))
# book__price去Book表找price
例3: 查詢每一個書名稱以及對應的作者的個數 (Book Author表)
ret=Book.objects.values("title").annotate(Count("authors")) ?????????
例4:
ret=Publish.objects.all().annotate(avg_price=Avg("book_price")).values("name","email","avg_price")
#前面的查詢結果 後面可以用????????????
例5: 查詢作者數不止一個的書名以及作者的個數 (重點看看)
ret=Book.objects.annotate(c=Count("authors").filter(c__gt=1).values("title","c"))
# c 添加到了Book對象的屬性中了
-------------------------------------------------------------------------
F和Q查詢:
F函數查詢
例1: 查詢評論數大於100的書名 以哪個字段分組 就把哪個字段放在values()裏
ret=Book.objects.filter(comment_count__gt=100).values("title")
例2: 評論數大於點贊數
from django.db.models. import F,Q (導入F Q函數)
ret=Book.objects.filter(comment_count__gt=F("poll_count"))
例3: 評論數大於2倍點贊數
ret=Book.objects.filter(comment_count__gt=F("poll_count")*2)
例4: 每本書的價格都在原價上加100
ret=Book.objects.all().update(price=100 + F("price"))
Q函數
例1: 查詢價格大於300或者評論數大於3000的書籍
ret=Book.objects.filter(Q(price__gt=300 | Q(comment_count__gt=3000)))
ORM的查詢