16 多表設計
阿新 • • 發佈:2020-12-02
1.表設計
''' BaseModel基表 is_delete、create_time、orders、updated_time 下面四表繼承基表,可以繼承兩個欄位 Book表: name、price、img、authors、publish is_delete、create_time、orders、updated_time Publish表: name、address is_delete、create_time、orders、updated_time Author表: name、age is_delete、create_time、orders、updated_time AuthorDetail表: mobile, author is_delete、create_time、orders、updated_time '''
2. 基表建立 (注意設定abstract = True)
from django.db import models class BaseModel(models.Model): """公共模型""" orders = models.IntegerField(default=1, verbose_name="排序", help_text='排序') # 預設不是刪除,資料庫中是0/1 is_delete = models.BooleanField(default=False, verbose_name="是否刪除", help_text='是否刪除') created_time = models.DateTimeField(auto_now_add=True, verbose_name="新增時間", help_text='新增時間') updated_time = models.DateTimeField(auto_now=True, verbose_name="修改時間", help_text='修改時間') class Meta: # 設定當前模型為抽象模型,在資料遷移的時候django就不會為它單獨建立一張表 abstract = True # 宣告該表只是一個抽象表不出現在資料庫中
3.斷關聯多表關係
db_constraint=False (設定了這個就是斷關聯,設定在外來鍵,刪除了作者詳情,也不會刪除作者)
3.1 作用
- 物理上斷開關係提升查詢效率
- 防止環裝表關係,導致表關係成為死表(即不能在操作表,如果想要在重新操作表,需要刪庫)
3.2 欄位設計
1、外來鍵位置: 一對多 -- 外來鍵放在多的一方 一對一 —— 從邏輯正反向考慮,如作者表與作者詳情表,作者刪除級聯作者詳情也刪除,詳情刪除作者依舊存在,所以建議外來鍵在 詳情表 中 多對多 -- 外來鍵在關係表中 2、ORM正向方向連表查詢 正向:通過外來鍵欄位 eg:author_detial_obj.author # 外來鍵設定在作者詳情表,在作者詳情表中查詢作者直接 .author就可以 反向:通過設定反向查詢related_name的值 eg:author_obj.detail #外來鍵沒有設定在作者表中,在作者表中通過設定反向查詢.detail查詢作者詳情 3、連表操作關係(外來鍵建在作者詳情表中) 1)作者刪除,詳情級聯 - on_delete=models.CASCADE #跟著一起刪除 2)作者刪除,詳情置空 - null=True, on_delete=models.SET_NULL #外來鍵欄位清空 3)作者刪除,詳情重置 - default=0, on_delete=models.SET_DEFAULT 4)作者刪除,詳情不動 - on_delete=models.DO_NOTHING
4.模型表設計
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False) # 預設不是刪除,資料庫中是0/1
create_time = models.DateTimeField(auto_now_add=True, verbose_name='建立時間')
# 設定 abstract = True 來宣告基表,作為基表的Model不能在資料庫中形成對應的表
class Meta:
abstract = True # 宣告該表只是一個抽象表不出現在資料庫中
class Book(BaseModel):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=5, decimal_places=2)
img = models.ImageField(upload_to='img', default='img/default.jpg')
# 關聯作者表
authors = models.ManyToManyField(
to='Author',
db_constraint=True, # 斷開關聯
related_name='books' # 反向查詢欄位
)
# 關聯出版社表
publish = models.ForeignKey(
to='Publish', # 關聯publish表
db_constraint=False, # 斷關聯(斷開Book表和Publish表的關聯,方便刪資料,雖然斷開了關聯但是還能正常使用)
related_name='books', # 反向查詢欄位:publish_obj.books就能查出當前出版社出版的的所有書籍
on_delete=models.DO_NOTHING, # 設定連表操作關係
)
@property
def publish_name(self):
return self.publish.name
@property
def authorlist(self):
return self.authors.values('name', 'age', 'detail__mobile').all()
class Meta:
db_table = 'book'
verbose_name = '書籍'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
# 出版社表
class Publish(BaseModel):
name = models.CharField(max_length=64)
addres = models.CharField(max_length=64)
class Meta:
db_table = 'publish'
verbose_name = '出版社'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
# 作者表
class Author(BaseModel):
name = models.CharField(max_length=64)
age = models.IntegerField()
class Meta:
db_table = 'author'
verbose_name = '作者'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
# 作者詳情
class AuthorDetail(BaseModel):
"""mobile, author、is_delete、create_time"""
mobile = models.CharField(max_length=11)
author = models.OneToOneField(
to='Author',
db_constraint=False,
related_name='detail',
on_delete=models.CASCADE
)
class Meta:
db_table = 'author_detail'
verbose_name = '作者詳情'
verbose_name_plural = verbose_name
def __str__(self):
return self.author.name