多表操作
一、Django多表orm設計規則
1. 關聯的表之間建議建立外鍵,但可以取消關聯關係(db_constraint=False)
2. 關聯表之間的外鍵字段建議採用對應類名的全小寫
3. 採用關聯表的主鍵或對象均能進行操作
# 例表設計:
# 書籍 Book: id name price publish_date publish author(多對多關聯字段)
# 出版社 Publish: id name address
# 作者 Author: id name author_detail
# 作者詳情 AuthorDetail: id age telephone info
modles設計:
# 一對多:出版社(一) 書籍(多,外鍵在多的一方,依賴於出版社)
# 一對一:作者詳情(一) 作者(一,外鍵在任意一方均可,一旦外鍵放在作者中,作者依賴於作者詳情)
# 多對多:作者(多)書籍(多)建立關係表(存放兩個表的外鍵信息 => 將建錶轉化為關係對應字段)
# Book書籍:id name price publish_date publish(publish_id)
class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField()
publish = models.ForeignKey(to='Publish', to_field='id')
# 多對多關係字段,該字段不會再book表中形成字段,是用來創建關係表的
author = models.ManyToManyField(to='Author')
# Author作者:id name
class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
# author_detail = models.ForeignKey(to='AuthorDetail', to_field='id', unique=True)
author_detail = models.OneToOneField(to='AuthorDetail', to_field='id')
# AuthorDetail作者詳情: id age telephone info
class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
age = models.IntegerField()
telephone = models.IntegerField()
# 存大文本
info = models.TextField()
# Publish出版社:id name address
class Publish(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=20)
address = models.CharField(max_length=64)
View Code
二、一對多關係
1、規則:
1. 關係中 『多』 依賴於 『一』
2. Django 1.x外鍵關聯默認有級聯刪除,2.x需要手動明確外鍵的級聯刪除(on_delete=models.CASCADE)
2、增刪改操作
# 1、增
# 先有出版社,才有書籍
publish = Publish.objects.create(name="老男孩出版社", address="上海核心基地")
# 外鍵為關聯對象
Book.objects.create(name='死亡Python', price=88.88, publish_date='2018-8-8', publish=publish) # 此處返回的是一個對象
id = Publish.objects.create(name="小女孩出版社", address="宇宙中心").id
# 外鍵字段為關聯對象主鍵
Book.objects.create(name='滅霸Linux', price=120.00, publish_date='2015-8-8', publish_id=id)
# 2、刪
# 刪除出版社,默認有級聯刪除,出版社出版的數據全會被刪除
Publish.objects.first().delete()
# 3、改
# 書籍的出版社修改必須為已存在的出版社
publish = Publish.objects.create(name="Owen出版社", address="御花園")
Book.objects.filter(pk=1).update(publish=publish) # pk代表主鍵
三、一對一關係
1、規則
通過外鍵所在表決定依賴關係,有外鍵的表依賴於外鍵所對應的另一張表。
2、增刪改操作
# 操作規則同一對多關係,有外鍵的表 依賴於 另一張表
# 增:遵循操作順序
author_detail = AuthorDetail.objects.create(age=18, telephone=13860357890, info="帥")
Author.objects.create(name='Sandy', author_detail=author_detail)
# 刪:擁有級聯刪除
AuthorDetail.objects.first().delete()
# 改:一般不考慮該關聯字段
四、多對多關係
1、規則:
1. 多對多關係存在關係表,關係表建議採用ManyToManyField字段處理;
2. 需要手動創建關係表時,在字段中明確through與through_field值。
2、增刪改操作:
通過關係表字段存在的類的對象獲取關係表 book.author
b1 = Book.objects.first() # type: Book
b2 = Book.objects.all()[1] # type: Book
a1 = Author.objects.first() # type: Author
a2 = Author.objects.all()[1] # type: Author
# 增:為書籍添加作者的主鍵或對象們
# book.author.add(*args) # 此處的book為Book的對象
b1.author.add(a1.id, a2.id)
b2.author.add(a1, a2)
# 刪:刪除書籍已有作者的主鍵或對象們
# book.author.remove(*args) # 此處的book為Book的對象
b1.author.remove(a1)
b1.author.remove(a2.id)
# 改:清空並添加作者的主鍵或對象 | 設置作者的主鍵或對象形式的列表
# book.author.clear() # 此處的book為Book的對象
b1.author.clear()
# book.author.add(*args) # 此處的book為Book的對象
b1.author.add(a1)
# book.author.set([*args]) # 此處的book為Book的對象
b2.author.set([a2.id, a3.id])
五、跨表查詢規則
1. 正向逆向概念:從存放外鍵的表到關係表稱之為正向跨表查詢,反之稱之為逆向查詢;
2. 正向查詢通過外鍵屬性名進行跨表查詢;
3. 逆向查詢通過關聯表對應類名小寫進行跨表查詢,逆向查詢遇到多條結果,在類名後再添加_set。
基於對象的跨表查詢
在跨表查詢的規則上,跨表查詢的結果為多條數據時需要在字段後添加_set
# 一對一
author = Author.objects.first() # 查詢得到作者對象
author_detail = author.author_detail # 基於對象跨表獲取作者詳情對象,正向通過字段名 author_detail
author = author_detail.author # 基於對象跨表獲取作者對象,逆向通過表名小寫 author
# 一對多
book = Book.objects.first() # 查詢得到書籍對象
publish = book.publish # 獲取出版社對象,正向通過字段名 publish
book_list = publish.book_set.all() # 獲取書籍對象們,逆向通過表名小寫 book,多條數據添加_set
# 多對多
book = Book.objects.first() # 查詢得到書籍對象
author_list = book.author # 獲取作者對象們,正向通過字段名 author
author = Author.objects.first()
book_list = author.book_set # 獲取書籍對象們,逆向通過表名小寫 book,多條數據添加_set
# 多級跨表
# 案例一:某作者出版的第一本書的出版社名字
author.book_set.first().publish.name
七、基於下劃線的跨表查詢
滿足跨表查詢規則
filter方法與values方法支持__查詢規則
# 案例
# 兩表關聯:查詢所有小於18歲作者的名字與實際年齡
authors_dic = Author.objects.filter(author_detail__id__gt=0).values('name', 'author_detail__age')
# 多表關聯:查詢出版社在上海的出版過的所有書的 作者姓名、作者電話、具體出版社名 的相關信息
info_dic = Book.objects.filter(publish__address__contains="上海").values('author__name', 'author__author_detail__telephone', 'publish__name')