DRF框架(六)——多表关系设计

BaseModel基表 models.py

# 基表
class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False) #默认不是删除,数据库中是0/1
    create_time = models.DateField(auto_now_add=True)

    # 作为基表的model不能在数据库中形成对应的表,设置abstract = True
    class Meta:
        abstract = True #声明该表只是一个抽象表不出现在数据库中

继承基表 models.py

# 书籍表
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')
    # 关联出版社表
    publish = models.ForeignKey(
        to='Publish', # 关联publish表
        db_constraint=False, #断关联(断开Book表和Publish表的关联,方便删数据,虽然断开了关联但是还能正常使用
        related_name='books', # 反向查询字段:publish_obj.books就能查出当前出版社出版的所有书籍
        on_delete=models.DO_NOTHING, # 设置连表操作关系
    )
    # 关联作者表
    authors = models.ManyToManyField(
        to='Author',
        db_constraint=False, #断开关联
        related_name='books' #反向查询字段
    )

    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)
    address = 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 = 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 '%s的详情' % self.author.name

 

多表关系断联 db_constraint=False

1、外键位置:

一对多关系 —— 外键放在多的一方

一对一关系 —— 从逻辑正反向考虑

  • 如作者表与作者详情表,作者删除级联作者详情也删除,详情删除作者依旧存在,所以建议外键在详情表中

多对多关系 —— 外键在关系表中

 

2、ORM正向方向连表查找:

正向:通过外键字段 eg: author_detial_obj.author

  • 外键设置在作者详情表,在作者详情表中查询作者直接.author就可以

反向:通过设置反向查询related_name的值 eg: author_obj.detail

  • 外键没有设置在作者表中,在作者表中通过设置反向查询.detail查询作者详情

 

3、连表操作关系:(外键在作者详情表中)

  • 作者删除,详情级联 —— on_delete=models.CASCADE # 跟着一起删除
  • 作者删除,详情置空 —— on_delete=models.SET_NULL #外键字段清空
  • 作者删除,详情重置 —— on_delete=models.SET_DEFAULT
  • 作者删除,详情不动 —— on_delete=models.DO_NOTHING

4、外键关联字段的参数 

  • ManyToManyField不能设置on_delete

  • OneToOneField、ForeignKey必须设置on_delete

  • Django1.x系统默认级联,但是Django2.X必须手动明确

作者详情表

author = models.OneToOneField(
    to='Author', #和作者表关联
    db_constraint=False, #范查询,作者表直接查作者详情表的电话号码,可以直接author_obj.detail.mobile
    related_name='detail', #断关联
    on_delete=models.CASCADE
)

图书表

    # 关联出版社表
    publish = models.ForeignKey(
        to='Publish', # 关联publish表
        db_constraint=False, #断关联(断开Book表和Publish表的关联,方便删数据,虽然断开了关联但是还能正常使用
        related_name='books', # 反向查询字段:publish_obj.books就能查出当前出版社出版的所有书籍
        on_delete=models.DO_NOTHING, # 设置连表操作关系
    )

    # 关联作者表
    authors = models.ManyToManyField(
        to='Author',
        db_constraint=False,
        related_name='books'
    )

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章