多表设计

多表设计

基表 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()
posted @ 2019-11-13 15:13  张明岩  阅读(155)  评论(0编辑  收藏  举报