序列化与反序列化基础

序列化与反序列化基础

序列化 => 后台数据到前台,反序列化 => 前台数据写到后台

1、内部类

1、概念

将类定义在一个类的内部,被定义的类就是内部类

2、特点

内部类及内部类的名称空间,可以直接被外部类访问

3、应用

通过内部类的名称空间,给外部类额外拓展一些特殊的属性(配置),典型的Meta内部类 - 配置类

class Book(model.Model):
    class Meta:
        db_model = "owen_book"  # 配置自定义表名
        
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = "Book"  # 配置序列化类绑定的Model表

2、DRF响应类:Response

drf的响应类Response内部属性有:

class Response(SimpleTemplateResponse):
    def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):

data:响应的数据 - 空、字符串、数字、列表、字典、布尔

status:网络状态码

template_name:drf自己也可以支持前后台不分离的返回页面,但是不能和data共存(不会涉及到)

headers:响应头

exception:是否有异常响应(如果异常可以赋值为True,没什么用)

content_type:响应的结果类型(响应式data默认是application/json)

常见响应:

from rest_framework import status
# 正常响应
Response(
    data={
        'status': 0,
        'msg': 'ok',
        'result': '正常数据'
    }
)
# 异常响应
Response(
    data={
        'status': 1,
        'msg': '客户端错误提示',
    },
    status=status.HTTP_400_BAD_REQUEST,
    exception=True
)

3、序列化基类控制的初始化参数

序列化serializers类继承的BaseSerializer类中初始化参数有以下的:

def __init__(self, instance=None, data=empty, **kwargs):
    pass

instance:是要被赋值对象的, - 对象类型数据赋值给instance

data:是被赋值数据的,- 请求来的数据赋值给data

kwargs:内部有三个属性:many、partial、context

  • many:操作的对象或数据是单个或多个

  • partial:在修改需求时使用,可以将所有的校验字段required校验规则设置为False

  • context:用于视图类和序列化类直接传参使用

常见使用:

# 单查接口
UserModelSerializer(instance = user_obj)
​
# 群查接口
UserModelSerializer(instance = user_query, many=True)
​
# 增接口
UserModelSerializer(data = request.data)
​
# 整体改接口
UserModelSerializer(instance = user_obj, data = request.data)
​
UserModelSerializer(instance = user_obj, data = requset.data, partial = True)
​
# 删接口用不到序列化类

4、反序列化

views.py

class UserAPIView(APIView):
    def post(self, request, *args, **kwargs):
        # 单增
        # 1)将前台请求的数据交给序列化类处理
        # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续
        # 3)序列化组件完成数据入库操作,得到入库对象
        # 4)响应结果给前台
        serializer = serializers.UserModelSerializer(data=request.data)
        if serializer.is_valid():  # is_valid校验
            # 校验成功 => 入库 => 正常响应
            obj = serializer.save()  # save内部入库
            return Response({
                'status': 0,
                'msg': 'ok',
                'result': serializers.UserModelSerializer(obj).data  # 新增的值返回
            }, status=status.HTTP_201_CREATED)
        else:
            # 校验失败 => 异常响应
            return Response({
                'status': 1,
                'msg': serializer.errors,  # errors错误信息
            }, status=status.HTTP_400_BAD_REQUEST)

serializers.py

开发流程:

  1. 在models类中自定义字段,在serializer类中自定义写字段

  2. 将models自带的字段和所有在model和serializer自定义的字段写在fields中,用write_only和read_only区别

  3. 可以在extra_kwargs中写基础的校验规则,也可以省略

  4. 制定局部钩子与全局钩子,全局钩子在上述所有校验后再校验

1、不管是序列化还是反序列化字段,都必须在field中进行声明,没有声明的不会参与任何过程(数据会被丢弃)

2、用read_only 表示只读,用write_only表示只写,不标注两者默认代表即可读也可写

3、models类中的自定义的字段@property声明的默认就是只读read_only

@property
def gender(self):
    return self.get_sex_display()

4、自定义的只写字段,在serializer类中需要自己手动声明write_only,serializer中自定义的字段必须明确write_only否则会报错,因为序列化会从model中强行反射自定义的字段,而model中没有该字段就会报错,而对于model中已经有的字段,在serializer类中再次声明会对model原有的字段进行覆盖,可以不明确write_only表示可读可写,并且要写在Meta上方同级的

re_password = serializers.CharField(write_only=True)

5、用extra_kwargs来为写的字段制定基础校验规则,可以在extra_kwargs中使用required代表是否必须参与写操作,有默认值和可以为空的时该值为False,反之为True,可以手动修改

# 制定简易基础校验规则查看有哪些规则
# serializers.DecimalField.max_value
# serializers.CharField.max_length
        extra_kwargs = {
            'name': {
                'required': True,
                'max_length': 32,
                'error_messages': {  # 可以被国际化配置替代
                    'max_length': '太长'
                }
            }
        }

6、每一个字段我们都可以自定义校验规则,使用局部钩子 validate_字段名(self, value) 方法来自定义校验规则,成功在返回value,失败在抛出exceptions.ValidationError('异常信息')异常

7、我们也可以使用全局钩子对好几个字段进行校验,比如password与re_password,使用validate(self, attrs),成功返回attrs,失败则抛出异常exceptions.ValidationError('异常信息')

from rest_framework import serializers
from . import models
from rest_framework import exceptions

​
# 制定简易基础校验规则查看有哪些规则
# serializers.DecimalField.max_value
# serializers.CharField.max_length
class UserModelSerializer(serializers.ModelSerializer):
    # 自定义字段,覆盖model中的字段,model中没有则必须写write_only=True
    pwd = serializers.CharField(max_length=8, min_length=4, write_only=True)
    re_pwd = serializers.CharField(max_length=8, min_length=4, write_only=True)
​
    class Meta:
        model = models.User
        # 将所有的字段都写在fields中
        fields = ['name', 'pwd', 'age', 'height', 'gender', 'img', 're_pwd']
        # 自定义基础的校验规则
        extra_kwargs = {
            'name': {
                # 有默认值或者可以为空,我们也可以限制必须提供
                'required': True,
                'max_length': 8,
                'error_messages': {  # 可以被国际化配置替代
                    'max_length': '太长'
                }
            }
        }
    # 局部与全局钩子与Meta同级,属性序列化类的
    # 自定义单个字段校验在局部钩子中校验,用validate_字段名(self, value)
    def validate_height(self, value):
        print(value)
        if value < 170:
            raise exceptions.ValidationError('太矮了')
        else:
            return value
​
    # 多字段之间校验用全局钩子,validate(self, attrs)  attrs是字段值的字典
    def validate(self, attrs):
        pwd = attrs.get('pwd')  # 只拿出来校验
        re_pwd = attrs.pop('re_pwd')  # 必须pop出来,不能存入数据库中
        if pwd != re_pwd:
            raise exceptions.ValidationError({'re_pwd': '两次密码不一致!'})
        else:
            return attrs

 

posted @ 2020-02-19 22:44  Mr沈  阅读(221)  评论(0编辑  收藏  举报