轉載自:https://www.cnblogs.com/zhaoyingjie/p/6984957.html
當在 model 定義是添加了 ForeignKey, OneToOneFiedl, ManyToMangField 的字段時, model 會自動生成相關 API 來獲取相關數據。
One-To-Many 關係
1、正向獲取 父表 to 子表
如果一個 model 包含有 ForeignKey 字段, 這個 model 的對象可以方便的獲取與之關聯的另一個 model 的對象。
例如: 獲取 Entry 對象對應的 Blog 對象
1 2 3 4 5 6 |
e = Entry.objects.get(id=2) e.blog # 返回通過外鍵關聯的 blog 對象 #如果要更新 e 對象的 blog 屬性 b = Blog.objects.get(id=3) e.blog = b e.save() # 執行根系操作, |
one-to-many 關係在第一次使用後將會被緩存
1 2 3 |
e = Entry.objects.get(id=2) print(e.blog) # 查詢數據, 並將數據緩存 print(e.blog) # 不查詢數據庫, 之間中緩存中讀取 |
使用 QuerySet 的 select_related() 方法時, 會將相應的 one-to-many 關係的對象都預先取出來並緩存, 在真正使用時就不會訪問數據庫
1 2 3 |
e = Entry.objects.select_related().get(id=2) print(e.blog) # 不查詢數據庫 print(e.bong) # 不查詢數據庫 |
2、反向獲取 子表 to 父表
如果 model A 通過 ForeignKey字段 field 與 model B 想關聯。 B 對象可以通過 model Manager 去訪問與之對應的所有的 A 對象。 默認的, 這個 model Manage 名爲 foo_set, 其中 foo 是擁有外鍵那個 model 名的小寫, 即 a_set()
例: 通過 Blog 對象查詢 Entry 對象:
1 2 3 4 5 6 |
# 查詢與 Blog 對象 b 關聯的所有 entry 對象 b = Blog.objects.get(pk=2) b.entry_set.all()
# 查詢與 Blog 對象 b 關聯的 entry 對象中 headline 包含 'Lennon' 的 b.entry_set.filter(headline__contains='Lennon') |
如果在定義 ForeignKey 字段時 通過 related_name 可以更改這個默認的 foo_set() Manage 方法。
例如: 將最頂部的 Entry Model 中的 blog 字段修改成如下: blog = ForeignKey(Blog, related_name=’entries’), 上面的代碼中的 entry_set 就可以都改成 entries。
1 2 3 4 5 6 |
# 查詢與 Blog 對象 b 關聯的所有 entry 對象 b = Blog.objects.get(pk=2) b.entries.all()
# 查詢與 Blog 對象 b 關聯的 entry 對象中 headline 包含 'Lennon' 的 b.entries.filter(headline__contains='Lennon') |
Many-To-Many 關係
對於 many-to-many 關係的 API 使用方法與上面的 one-to-many 關係的一致。區別在於, 在命名 ManyToMany 字段時, 字段名不要與其對應的 model 名的小寫一致。例如 Entry 中, authors 字段名稱不與其對應 Model(Author) 的小寫名 author 相同。 這點與 blog 字段不同。
1 2 3 4 5 6 7 8 |
e = Entry.objects.get(id=3) e.authors.all() # 返回 e 對象對應的所有 authors e.authors.count() # authors 的數量 e.authors.filter(name__contains='John') # 返回名字中包含 John 的作者
a = Author.objects.get(id=5) # 返回所有與 a 對象對應的 Entry 對象 a.entry_set.all() |
One-To-One 關係
One-to-one 關係同 many-to-one 非常相似, API 用法與 many-to-one 的基本也基本一致
1 2 3 4 5 6 |
class EntryDetail(models.Model): entry = models.OneToOneField(Entry, on_delete=models.CASCADE) details = models.TextField()
ed = EntryDetail.objects.get(pk=3) en.entry # 返回與之對應的 Entry 對象 |
與 many-to-one 不同的是其反向查找, 如下:
1 2 3 4 5 6 7 8 |
e = Entry.objects.get(pk=3) # 取得與 Entry 對象對應的 EntryDetail 對象, # 只需調用 EntryDetail 的小寫 entrydetail 即可 e.entrydetail
#更新 e.entrydetail = ed2 e.save() |