断关联表关系有优点也有缺点, 先看代码:
- from django.db import models
- # Book 表:
- # Publish 表:
- # Author 表:
- # AuthorDetail 表:
- from django.contrib.auth.models import User
- class BaseModel(models.Model):
- is_delete = models.BooleanField(default=False)
- created_time = models.DateTimeField(auto_now_add=True)
- class Meta:
- # 基表, 为抽象表, 是专门用来被继承, 提供公有字段的, 自身不会完成数据库迁移
- abstract = True
- # 断关联表关系
- # 1)不会影响连表查询操作效率
- # 2)会提升连表增删改操作效率
- # 3)易于后期数据库表的重构
- # 4)缺点在于: 数据库本身没有连表检测, 容易出现脏数据, 需要通过严格的逻辑避免脏数据的参数(必要的时候管理脏数据)
- # 举例: A 依赖 B, 先插入 A 记录, 该记录对应的 B 记录没产生, 在没有关联的情况下, 该操作可以实现, 但是数据就是脏数据
- # 接着再将 B 数据添加, 脏数据就得到处理了. 反过来先操作 B 后操作 A, 更满足逻辑思维, 一样可以执行. 通过逻辑将 AB 表进行
- # 连表查询, 不会有任何异常
- """
- 表关系
- 1)Book 和 Publish 一对多: 外键在多的一方 Book
- 2)Book 和 Author 多对多: 外键在查询频率高的一方 Book
- 3)Author 和 AuthorDetail 一对一: 外键要根据实际需求建立在合理的位置 AuthorDetail
- """""" 外键字段属性
- 1)related_name 在外键中设置外键反向查询的字段名: 正向找字段名, 反向找 related_name 值
- 2)on_delete 在外键中必须设置, 表示级联关系, 在 Django 1.x 下, 系统默认提供(值为 models.CASCADE),Django 2.x 下, 必须手动明确
- CASCADE: 默认值, 级联
- 例子: 作者没, 详情一定没, 存在没意义
- DO_NOTHING: 外键不会被级联, 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段不做任何处理
- 例子: 作者没, 书还是作者写的 | 出版社没, 书还是该出版社出版的
- SET_DEFAULT: 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段置为 default 属性设置的值, 所以必须配合 default 属性使用
- 例子: 部门没, 部门员工进入待定部门(注: 部门表一定要有待定部门记录)
- SET_NULL: 假设 A 表依赖 B 表, B 记录删除, A 表的外键字段置为 null, 所以必须配合 null=True 属性使用
- 例子: 部门没, 部门员工进入未分组部门(注: 关联部门表外键可以为空)
- 注: 多对多字段不能设置 on_delete 级联关系, 默认为级联, 如果要处理级联关系, 需要手动明确关系表, 处理关系表中的多个外键
- 3) db_constraint 在外键中控制表关联, 默认为 True 表示关联, 设置 False 表示断开关联
- """
- class Book(BaseModel):
- name = models.CharField(max_length=64)
- price = models.DecimalField(max_digits=10, decimal_places=2)
- publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING, null=True)
- authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)
- def __str__(self):
- return self.name
- class Publish(BaseModel):
- name = models.CharField(max_length=64)
- address = models.CharField(max_length=64)
- class Author(BaseModel):
- name = models.CharField(max_length=64)
- class AuthorDetail(BaseModel):
- mobile = models.CharField(max_length=64)
- author = models.OneToOneField(to=Author, related_name='detail', db_constraint=False, on_delete=models.CASCADE)
子序列
只能在序列化中使用
字段名必须是外键 (正向反向) 字段
因为相对于自定义序列化外键字段, 自定义序列化字段是不能参与反序列化的, 而子序列化必须为外键名, 所以就无法入库
在外键关联数据是多条时, 需要明确 many=True
是单向操作, 因为作为子序列化的类必须写在上方, 所以不能产生逆方向的子序列化
- # 出版社群查
- class PublishAPIView(APIView):
- def get(self, request, *args, **kwargs):
- publish_query = models.Publish.objects.all()
- publish_ser = serializers.PublishModelSerializer(publish_query, many=True)
- return Response({
- 'status': 0,
- 'msg': 'ok',
- 'results': publish_ser.data
- })
- class PublishModelSerializer(serializers.ModelSerializer):
- class Meta:
- model = models.Publish
- # fields = '__all__'
- fields = ['name', 'address', 'books']
来源: http://www.bubuko.com/infodetail-3356847.html