drf-外键字段设置及子序列化

踩风火轮的乌龟 2019-12-30

目录

基表

  • 基表只提供公有字段, 不参与数据库迁移
  • 在基表下的配置类class Meta:中设置: abstract = True, 表明该表为抽象表, 不参与数据库迁移
Copy# 基表
class Base(models.Model):  
    is_delete = models.BooleanField(default=False)
    created_time = models.DateTimeField(auto_now=True)
    
    class Meta:
        # 表明该表为抽象表, 只提供公有字段, 不参与数据库迁移 
        abstract = True

外键字段参数

db_constraint 数据库关联#

  • 断关联: db_constraint=False, 既数据库中不会建立外键关系, Django在代码层面上实现两表关联
  • 优点
    • 不会影响连表查询操作效率
    • 可以提升连表增删改效率
    • 易于后期数据库表的重构
  • 缺点
    • 数据库本身没有连表检测, 容易出现脏数据 (需要通过严格的逻辑避免, 必要时管理脏数据)
Copyclass Book(Base):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=6, decimal_places=2)
    press = models.ForeignKey(to='Press', related_name='books', db_constraint=False, on_delete=models.SET_NULL, null=True)
    authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)


class Press(Base):
    name = models.CharField(max_length=64)
    addr = models.CharField(max_length=64)


class Author(Base):
    name = models.CharField(max_length=64)
    # 逻辑不合理
    # author_detail = models.OneToOneField(to='AuthorDetail')


class AuthorDetail(Base):
    mobile = models.CharField(max_length=64)
    author = models.OneToOneField(to=Author, related_name='detail', db_constraint=False, on_delete=models.CASCADE)

related_name: 反向查询辅助名#

Copy"""
在外键字段中设置related_name: 
1.为反向查询的辅助字段名(正向查询按字段属性, 反向查询按related_name)
2.related_name可以作为字段名参加序列化类中的fields设置
"""

on_delete 级联关系#

Copy"""
A表依赖B表, b记录删除,
    on_delete=models.CASCADE                    a记录也会被删除
    on_delete=models.DO_NOTHING                 a记录对应外键字段不受影响
    on_delete=models.SET_DEFAULT, default=1     a记录对应外键字段变为默认值
    on_delete=models.SET_NULL, null=True        a记录对应外键字段变为null
    注:多对多外键字段不能修改级联关系, 默认是 on_delete=models.CASCADE
"""

子序列化

  • 只能在序列化类中使用
  • 子序列化的字段名必须是外键字段(正向反向都可以, 包括related_name)
  • 子序列化字段关联多条数据时, 需要明确 many=True
  • 子序列化是单向的, 原因很简单, 一个位置在上, 一个位置在下
Copyclass BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = ['name']


class PressModelSerializer(serializers.ModelSerializer):
    # 子序列化字段
    books = BookMethodSerializer(many=True)

    class Meta:
        model = models.Press
        fields = ['name', 'addr', 'books']
Copy# 使用子序列化的返回结果
{
    "status": 0,
    "msg": "ok",
    "result": [
        {
            "name": "东方出版社",
            "addr": "上海",
            "books": [
                {
                    "name": "三体"
                },
                {
                    "name": "球状闪电"
                }
            ]
        },
        {
            "name": "北方出版社",
            "addr": "北京",
            "books": [
                {
                    "name": "今日简史"
                }
            ]
        }
    ]
}


-----------------------------------------------------------------------------------------------------


# 未使用子序列化的返回结果
{
    "status": 0,
    "msg": "ok",
    "result": [
        {
            "name": "东方出版社",
            "addr": "上海",
            "books": [
                1,
                3
            ]
        },
        {
            "name": "北方出版社",
            "addr": "北京",
            "books": [
                2
            ]
        }
    ]
}

相关推荐