1. 程式人生 > >7 多表操作

7 多表操作

play 分隔 man pan 反向查詢 model bject 記錄 publish

一、多表之間的關系

 1 一對一:
 2 1?? 必須對先被關聯表添加記錄(即沒有外鍵的表)
 3 2?? 關聯表中的關聯字段可以直接使用被關聯表時的對象
 4 創建關聯表時,可直接使用外鍵 id 傳入被關聯表中未被綁定的元素
 5 
 6 一對多:
 7 1?? 必須對先被關聯表添加記錄(即沒有外鍵的表)
 8 2?? 關聯表中的關聯字段可以直接使用被關聯表時的對象
 9 3?? 過濾出被關聯表的對象記得加上 first() 處理
10 4?? 讓關聯表 id = 被關聯表 id
11 
12 多對多:
13 1?? 添加關聯關系使用 book.authors.add(1,2),表示的是往中間表插入記錄,沒有返回值
14 book:表示的是對應的 book 某本書,而不是在創建表時的 authors 屬性 15 1,2:表示的是 authors.id 16 2?? book.authors.add(*(1,2)) 17 3?? add(參數1,參數2) # 參數可以直接傳對象,以逗號分隔

1 解除綁定關系

remove() # 需要傳參數,參數即需要解除的 id 或者對象,可以是多個,用逗號分隔;也可用解壓的方式(*(參數1,參數2))

2 一次性清空綁定關系

clear()  # 不用傳參數

3 先清空再設置

set()  # 底層原理是先清空,然後再使用  add() 函數來添加;參數必須是可叠代對象

二、多表查詢的總結

技術分享圖片
authordetail = AuthorDetail.objects.filter(pk=zhf.authordetail_id)
print(zhf.authordetail)

# 這種情況下會查詢兩次,第一次是 authordetail 這個表中查詢一次;第二次是 zhf.authordetail 執行查詢一次
Notice

1 正向查詢與反向查詢

正向查詢:關聯字段在 A 表中,查詢表 B,按字段來查詢,即 A.B.字段名

反向查詢:關聯字段在 A 表中,由表 B 查詢 表 A,按照 表名小寫_set 方式來查詢
如:B.a_set.all()
B.a_set 是 Manage 對象
B.a_set.all() 是 QuerySet 對象

2 正向查詢方式與反向查詢方式

總結 正向查詢 反向查詢
one to one 按照字段 表名小寫
one to many 按照字段 表名小寫_set
many to many 按照字段 表名小寫_set

三、基於雙下劃線的多表查詢(鏈表查詢)

Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關系,它能自動確認 SQL JOIN 聯系。要做跨關系查詢,就使用兩個下劃線來鏈接模型(model)間關聯字段的名稱,直到最終鏈接到你想要的model 為止。

  正向查詢按字段,反向查詢按表名小寫用來告訴ORM引擎join哪張表

1 在使用 __ 雙下劃線告訴 ORM 該 JOIN 哪張表前提下的總結

總結 正向查詢 反向查詢
one to one 按照字段 表名小寫
one to many 按照字段 表名小寫
many to many 按照字段 表名小寫

四、聚合函數

form django.db.models.import Avg,Count,Max,Min,Sum
# 使用 aggregate() 函數表示聚合函數

Book.objects.all.aggregate(Avg(price))  # 返回值是一個字典,可傳多個參數
# 給字段重命名
Book.objects.all.aggregate(avg_price=Avg(price)) 

五、分組

annotate() 為調用的 QuerySet 中每一個對象都生成一個獨立的統計值(統計方法用聚合函數)。

from django.db.models import Avg, Max, Sum, Min, Max, Count
book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
for book in book_list:
     print(book.name)
     print(book.author_num)
book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values(name,author_num)
print(book_list)

總結 :跨表分組查詢本質就是將關聯表 JOIN 成一張表,再按單表的思路進行分組查詢。 

技術分享圖片
1?? value 在 annotate 前,表示group by 字段;在 annotate 後,表示要 select 的字段(若不寫 value,默認是以基表的主鍵為基準)
2?? filter 在 annotate 前,指的是 where 的東西;在 annotate 後面指的是 having 的東西
Notice

六、F 查詢和 Q 查詢

1 F 查詢

  Django 提供 F() 函數。F() 的實例可以在查詢中引用字段,來比較同一個 model 實例中兩個不同字段的值。Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操作。修改操作也可以使用F函數。

from django.db.models import F,Q
#評論數大於閱讀數的所有書,返回的是 QuerySet 對象
Book.objects.all().filter(commit_num__gt=F(read_num))

# 對所有的書價格 +1
Book.objects.all().update(price=F(price)+1)

2 Q 查詢

  filter() 等方法中的關鍵字參數查詢都是一起進行“AND” 的。 若需要執行更復雜的查詢(例如 OR 語句),可以使用 Q 對象

  Q 對象可以使用 & 和 | 操作符組合起來。當一個操作符在兩個 Q 對象上使用時,它產生一個新的 Q 對象。

bookList=Book.objects.filter(Q(authors__name="888")|Q(authors__name="666"))

# 等同於 SQL 語句
WHERE name ="yuan" OR name ="egon"
技術分享圖片
如果出現Q 對象,它必須位於所有關鍵字參數的前面
bookList=Book.objects.filter(Q(publish_Date__year=9999) | Q(publish_Date__year=8888), name__icontains="Django")
Notice

7 多表操作