The sequences of the DRF, model type (IV)

A secondary package Resonse

responses.py
from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self, status=None, msg=None, http_status=None, *args, **kwargs):
        data = {
            'status': status,
            'msg': msg,
        }
        if kwargs:
            data.update(kwargs)
        super().__init__(status=http_status,data=data)

Second, the relationship between the analysis database

'''
1.相互有关系的两张表,增删改操作会相互影响,导致效率低下,查询操作就是正常的连表操作

2.相互有关的两张表,断开外键关系,但从代码逻辑层面保持原来的联系
    - 这样一来,每个表都可以单独操作,提高了增删改查的效率,在开发中要避免由此带来的脏数据,事务 + 代码层面的逻辑约束
    - 由于数据没有发生变化,查询的连表操作不会受到影响

3. django的orm支持断关联操作关系表,且所有的操作方式和没有断开关联的操作是一致的(在django2.0以上默认不进行级联更新)

'''

Three, orm operation relations

'''
外键位置:
1.一对多的外键关系,FK毫无疑问建立在多的乙方,如书与出版社,外键应该放在书表中。
2.多对多的外键关系,ManyToManyField放在任一一端都可以,因为会创建第三章关系表,在关系表中用两个外键分别关联两个表

3.一多一的的外键关系,OneToOneField放在依赖的表,如作者与作者详情表,作者详情依赖于作者,所以将其放在作者详情表。
OneToOneField会被转换为外键+ 位移约束。

'''

'''
ORM关系Field:
ForeignKey可以设置related_name, db_constraint, on_delete
OneToOneField可以设置related_name, db_constraint, on_delete
ManyToManyField只能设置related_name, db_constraint
    - 不能设置on_delete的原因:无论放在A表还是B表,第三张表都会受到影响。
    - 可以自定义关系表,在关系表的两个外键分别设置on_delete
'''

'''
各参数的含义:
related_name:表之间反向访问的名字,默认是表名小写|表名小写_set
db_constraint:表之间的关联关系,默认为True为关联。设置为False,可以提高增删改查的效率,且不影响其他操作
on_delete:在django 1.x下默认是CASCADE,在django 2.x中需要手动。
'''

'''
表关系:
作者详情依赖于作者,作者被删除跟着被删除:CASCADE
作者与书的关系,当作者被删除,书不变:DO_NOTHING

部门表与员工表,一条部门记录被删除时,
部门内的员工全部进入未分组部门:SET_DEFAULT(需要配合default属性使用)
部门内的员工外键字段设置为空:SET_NULL(需要配合null=True属性使用)
'''
Test Case
import os, django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day69.settings")
django.setup()

from api.models import Author, AuthorDetail

# print(Author.objects.all())
# print(AuthorDetail.objects.all())
#
# AuthorDetail.objects.first().delete() # type Author
#
# print(Author.objects.all())
# print(AuthorDetail.objects.all())

obj = Author.objects.first()
print(obj.name,obj.detail.phone)

d_obj = AuthorDetail.objects.first()
print(d_obj.phone,d_obj.author.name)

Fourth, the base table

# 基类:是抽象的(不会完成数据库迁移),目的是提供共有字段的
class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    updated_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True  # 必须完成该配置
Inheritance base table

class Book(BaseModel):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
    image = models.ImageField(upload_to='img', default='img/default.png')

    publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING)
    authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)


class Publish(BaseModel):
    name = models.CharField(max_length=64)


class Author(BaseModel):
    name = models.CharField(max_length=64)


class AuthorDetail(BaseModel):
    phone = models.CharField(max_length=11)
    author = models.OneToOneField(
        to=Author,
        related_name='detail',
        db_constraint=False,
        on_delete=models.SET_NULL,
        null=True
    )

V. Other configuration sequence class (learn)

class AuthorModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        # 不常用,将全部字段提供给外界
        fields = '__all__' 
        
# ------------------------------------------------------------------

class AuthorModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        # 不常用,排除指定字段的其他所有字段,不能自动包含 外键反向 字段
        exclude = ['is_delete', 'updated_time']  
        
# ------------------------------------------------------------------

class AuthorModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        # 'detail', 'books' 是 外键(正向|反向) 字段
        fields = ['name', 'detail', 'books']
        # 不常用,自动深度,自动深度会显示外键关联表的所有字段
        depth = 2  
# 正向外键字段:就是外键的属性名
# 反向外键字段:就是外键属性设置的related_name

Six sequences of

'''
1.子序列化的字段,必须是外键(正向或反向)字段
2.子序列化对应的数据单个many=False,多个对应many=True
3.子序列化其实就是自定义序列化字段,覆盖了原有外键字段的规则,所以不能进行反序列化********

'''
Case

serializers.py

from rest_framework import serializers
from . import models

class AuthorDetailModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.AuthorDetail
        fields = ['phone']

# 子序列化detail字段
class AuthorModelSerializer(serializers.ModelSerializer):
    detail = AuthorDetailModelSerializer(many=False)
    class Meta:
        model = models.Author
        fields = ['name','detail']
        
# 子序列化author字段
class BookModelSerializer(serializers.ModelSerializer):
    author = AuthorModelSerializer(many=True)
    class Meta:
        model = models.Book
        # fields = ['name', 'price']
        # fields = '__all__'
        # exclude = ['is_delete','create_time']
        # depth = 1
        fields = ['name', 'price', 'author']

Seven multi-table serialization and de-serialization

'''
1.外键字段要参与反序列化,所以外键字段设置为write_only
2.外键关系需要联表序列化结果(而不是仅返回外键字段的id),可以在model中自定义@property来自定义联表序列化
'''

Complete deserialization only needs to be declared in the foreign key fields in field

class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # author和publish都为外键字段
        fields = ['name', 'price', 'author','publish']
# 请求数据格式----drf能自动识别需要接受的类型如[]
{
    "name":"西游记1",
    "price":"6.66",
    "author":[2,3],
    "publish":1
}

Serialized data : since the foreign key column left deserialization used, needs to be defined in the model class attributes @property (default serialization involved only) and set the original foreign key field write_only

serializers.py
class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # author和publish都为外键字段
        fields = ['name', 'price', 'author','publish','publish_name','author_list']     
        extra_kwargs = {
            'author':{
                'write_only':True
            },
            'publish': {
                'write_only': True
            }
        }
models.py
class Book(BaseModel):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=8, decimal_places=2)

    publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING)
    author = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)

    @property
    def publish_name(self):
        return self.publish.name

'''方式一
    @property
    def read_author_list(self):
        a_list = []
        for author_obj in self.author.all():
            info_dict = {}
            info_dict['name'] = author_obj.name
            # detail字段可能为空
            try:
                info_dict['phone'] = author_obj.detail.phone
            except:
                info_dict['phone'] = ''
            a_list.append(info_dict)
        return a_list
'''

# 方式二:需要辅助类
    @property
    def author_list(self):
        from .serializers import AuthorModelSerializer
        return AuthorModelSerializer(self.author.all(),many=True).data

views.py
from rest_framework.views import APIView
from . import models
from . import serializers
from .responses import APIResponse
from rest_framework import status

# 六个必备接口:单查(✔)、群查(✔)、单增(✔)、单删、单整体改(了解)、单局部改
# 四个额外接口:群增(✔)、群删、群整体改、群局部改
class BookAPIView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        if pk:
            obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
            if obj:
                serializer = serializers.BookModelSerializer(obj, many=False)
                return APIResponse(status=0, msg='ok', result=serializer.data, http_status=200)
            else:
                return APIResponse(status=0, msg='data not exists')
        else:
            objs = models.Book.objects.all()
            serializer = serializers.BookModelSerializer(objs, many=True)
            return APIResponse(status=0, msg='ok', result=serializer.data, http_status=200)

    def post(self, request, *args, **kwargs):
        data = request.data
        # 是否多个数据进行判断
        # 单增
        if not isinstance(data, list):
            serializer = serializers.BookModelSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            obj = serializer.save()
            return APIResponse(status=0, msg='ok', result=serializers.BookModelSerializer(obj, many=False).data,
                               http_status=201)
        # 群增
        else:
            serializer = serializers.BookModelSerializer(data=data,many=True)
            serializer.is_valid(raise_exception=True)
            objs = serializer.save()
        # 将objs重新序列化返回给前端(序列化与反序列化信息不对等)
            return APIResponse(status=0,msg='ok',result=serializers.BookModelSerializer(objs,many=True).data,http_status=status.HTTP_201_CREATED)

        
# 友情注释:群增其实是借助了ListSerializer来的create方法完成的

summary

"""
1)二次封装Response:
    自定义类继承Response,重写init方法,在内部格式化data
    
2)表关系分析:
    断关联:
        优点:提示增删改操作效率,不允许查效率
        缺点:增删改操作可能会导致脏数据,所以需要通过逻辑或是事务来保证
        
3)ORM表关系处理语法:
    1)外键所在位置
    2)如何断关联db_constraint
    3)正向方向自定义名字:related_name
    4)表关系:on_delete四种
    
4)基表:Meta中配置abstract=True,来被继承,提供共有字段

5)多表连表Meta中的了解配置
    fields = '__all__'  # 不常用,将全部字段提供给外键
    exclude = ['is_delete', 'updated_time']  # 不常用,排除指定字段的其他所有字段
    depth = 2  # 不常用,主动深度,自动深度会显示关联表的所有字段
    
6)子序列化
    i)通常只用于序列化过程,对外键字段进行了覆盖,影响外键字段的反序列化过程
    class SubSerializer:
        pass
    class SupSerializer:
        外键 = SubSerializer(many=True|False)
    
7)多表的序列化与反序列化
    1)连表序列化用自定义@property完成:内部实现可以自定义逻辑,也可以走序列化类
    2)外键字段留给反序列化来使用
    
8)单查、群查、单增、群增接口
"""

Guess you like

Origin www.cnblogs.com/Ghostant/p/12348054.html