多表设计
基表 my_utils/model.py
utils/model.py
from django.db import models
class BaseModel(models.Model):
create_time = models.DateTimeField(auto_now_add=True, null=True)
is_delete = models.BooleanField(default=False)
class Meta:
# 抽象表,不会完成数据库迁移
abstract = True
多表关系 api/models.py
模型:api/models.py
from django.db import models
from my_utils.model import BaseModel
# 断表的原因是:必须得有author 才有 authors
# Create your models here.
'''
Book 表: name price img
Author 表:name age
Author_detail 表:phone
Publish 表: name address
Book Author 多对多
Book Publish 多对一
Author Author_detail 一对一
'''
'''
总结就是一句话:断外键+设置逻辑级联删除方式+不影响链表操作
多表关系总结:
一对一:Author AuthorDetail两表
1)关系放在AthorDetail表中:作者删除详情删除,详情删除作者保留
2)作用找详情用 外键related_name(detail),详情找作者用 外键字段(author)
下面的设置一句话:断外键,orm依然可以链表操作,orm层面级联删除
author = models.OneToOneField(to=Author,null=True,related_name='detail',# 用于author表链表本表记录
db_constraint=False,# 断掉外键关系,但是orm可以进行链表操作。
on_delete=models.CASCADE # orm逻辑上进行级联删除
)
一对多:Book、Publish两表
1)关系字段应该放在Book表中(多的一方):删除书 出版社保留, 出版社删 除书删掉(下面会解决)
2)出版社找书用 外键related_name(books),书找出版社 外键字段(publish)
----下面的设置一句话:断外键,orm依然可以链表操作,orm层面级联删除动作取消
publish = models.ForeignKey(to='Publish',null=True,
related_name='books', # 用于反向查询
db_constraint=False, # 断开外键
on_delete=models.DO_NOTHING # 级联删除无动作
)
外键字段的其它关联方式
1)断关联,删除关联表记录,外键值置空
db_constraint=False, on_delete=models.SET_NULL, null=True,
2)断关联,删除关联表记录,外键值置默认值
db_constraint=False, on_delete=models.SET_DEFAULT, default=1,
多对多:Book、Author两表
1)关系字段放在任意一方都可以:出版社删除或书删除彼此不影响,但关系表一定级联删除
2)正向找 外键字段,反向找 外键字段related_name
3)db_constraint断开表关联,多对多on_delete不存在(不设置,本质在第三张表中设置,且一定是级联)
authors = models.ManyToManyField(to='Author', null=True,
related_name='books',
db_constraint=False,
)
'''
class Book(BaseModel):
name = models.CharField(max_length=64,null=True)
price = models.DecimalField(max_digits=5,decimal_places=2,null=True)
img = models.ImageField(upload_to='img',default='img/default.png')
# 多对多
authors = models.ManyToManyField(to='Author',
# related_name = 'books',
# db_constraint = False,
)
# 多对一
publish = models.ForeignKey(to='Publish',null=True,
related_name='books', # 用于反向查询
db_constraint=False, # 断开外键
on_delete=models.DO_NOTHING # 级联删除无动作
)
class Meta:
db_table = 'lf_book'
verbose_name = '书籍'
verbose_name_plural =verbose_name
class Author(BaseModel):
name = models.CharField(max_length=64,null=True)
age = models.IntegerField(null=True)
class Meta:
db_table = 'lf_author'
verbose_name = '作者'
verbose_name_plural =verbose_name
# 一对一
class AuthorDetail(BaseModel):
author = models.OneToOneField(to=Author,null=True,related_name='detail',# 用于author表链表本表记录
db_constraint=False,# 断掉外键关系,但是orm可以进行链表操作。
on_delete=models.CASCADE # orm逻辑上进行级联删除
)
phone = models.CharField(max_length=11,null=True)
class Meta:
db_table = 'lf_author_detail'
verbose_name = '作者详情'
verbose_name_plural =verbose_name
class Publish(BaseModel):
name = models.CharField(max_length=64,null=True)
address = models.CharField(max_length=80,null=True)
class Meta:
db_table = 'lf_publish'
verbose_name = '出版社'
verbose_name_plural = verbose_name
测试代码:script/t_dg.py
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dg_proj.settings")
import django
django.setup()
from api import models
# 一对一
# author = models.Author.objects.first() # type: models.Author
# print(author.name)
# print(author.detail.mobile)
# author.delete()
# author_detail = models.AuthorDetail.objects.first() # type: models.AuthorDetail
# print(author_detail.mobile)
# print(author_detail.author.name)
# author_detail.delete()
# 一对多
# publish = models.Publish.objects.filter(pk=2).first() # type: models.Publish
# print(publish.name)
# print(publish.books.first().name)
# publish.delete()
# publish = models.Publish.objects.filter(is_delete=False).first() # type: models.Publish
# if publish:
# print(publish.name)
# print(publish.books.first().name)
# publish.is_delete = True
# publish.save()
# book = models.Book.objects.first() # type: models.Book
# print(book.name)
# print(book.publish.name)
# book.delete()
# 多对多
# book = models.Book.objects.first() # type: models.Book
# print(book.name)
# print(book.authors.first().name)
# book.delete()
author = models.Author.objects.first() # type: models.Author
print(author.name)
print(author.books.first().name)
author.delete()