zoukankan      html  css  js  c++  java
  • 68 drf 响应类reponse 序列化数据校验与写入

    1.内部类

    就是当前类的配置类

    1.序列化组件的配置类

    2.数据库model配置类

     解释: 伪代码         继承的model类支持db_name,所以Meta类要使用db_name的写法

    """
    class Car(Model):
        name = CharFields()
        class Meta:
            db_name = "表名"
    
    # Car表,将会name作为Car表的字段
    (内部可以通过Car.name访问到name)
    (内部可以通过Car.Meta.db_name访问到 "表名" => table的表名)
        if Car.Meta.db_name:
            table的表名 = Car.Meta.db_name
        else:
            table的表名 = Car.__class__.name
    """

    2.响应类分析  reponse

    1.reponse类源码分析

    响应类Response源码
    
    def __init__(self, data=None, status=None,
                     template_name=None, headers=None,
                     exception=False, content_type=None):
        pass
        
    data:响应的数据 - 空、字符串、数字、列表、字段、布尔
    status:网络状态码
    template_name:drf说自己也可以支持前后台不分离返回页面,但是不能和data共存(不会涉及)
    headers:响应头(不用刻意去管)
    exception:是否是异常响应(如果是异常响应,可以赋值True,没什么用)
    content_type:响应的结果类型(如果是响应data,默认就是application/json,所有不用管)

    2.运用

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status    #网络状态码模块 可以进去看源码
    
    from . import models, serializers
    
    class UserAPIView(APIView):
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:  # 单查
                # 1)数据库交互拿到资源obj或资源objs
                # 2)数据序列化成可以返回给前台的json数据
                # 3)将json数据返回给前台
                try:
                    obj = models.User.objects.get(pk=pk)
                    serializer = serializers.UserModelSerializer(obj, many=False)
                    return Response({
                        'status': 0,
                        'msg': 'ok',
                        'result': serializer.data
                    })
                except:
                    return Response(
                        data={
                            'status': 1,
                            'msg': 'pk error'
                        },
                        status=status.HTTP_400_BAD_REQUEST,  # 比直接写400更具有描述性
                        exception=True
                    )

    3.序列化参数分析 

    1.源码分析    

    序列化类BaseSerializer
    def __init__(self, instance=None, data=empty, **kwargs):
        pass
    
    instance:是要被赋值对象的 - 对象类型数据赋值给instance
    data:是要被赋值数据的 - 请求来的数据赋值给data
    kwargs:内部有三个属性:many、partial、context
        many:操作的对象或数据,是单个的还是多个的
        partial:
        context:   下面两个参数后期会讲

    2.运用    序列化实现单查  群查

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    
    from . import models, serializers
    
    class UserAPIView(APIView):
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:  # 单查
                # 1)数据库交互拿到资源obj或资源objs
                # 2)数据序列化成可以返回给前台的json数据
                # 3)将json数据返回给前台
                try:
                    obj = models.User.objects.get(pk=pk)
                    serializer = serializers.UserModelSerializer(obj, many=False)      instance  
                    return Response({
                        'status': 0,
                        'msg': 'ok',
                        'result': serializer.data
                    })
                except:
                    return Response(
                        data={
                            'status': 1,
                            'msg': 'pk error'
                        },
                        status=status.HTTP_400_BAD_REQUEST,  # 比直接写400更具有描述性
                        exception=True
                    )
    
            else:  # 群查
                # 1)数据库交互拿到资源obj或资源objs
                # 2)数据序列化成可以返回给前台的json数据
                # 3)将json数据返回给前台
                queryset = models.User.objects.all()
                serializer = serializers.UserModelSerializer(queryset, many=True)
                return Response({
                        'status': 0,
                        'msg': 'ok',
                        'results': serializer.data
                    })
    
        def post(self, request, *args, **kwargs):
            # 单增
            # 1)从请求request中获得前台提交的数据
            # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成)
            # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码)
            # 4)将json数据返回给前台
    
            # 1)将前台请求的数据交给序列化类处理
            # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续
            # 3)序列化组件完成数据入库操作,得到入库对象
            # 4)响应结果给前台
            serializer = serializers.UserModelSerializer(data=request.data)
            if serializer.is_valid():
                # 校验成功 => 入库 => 正常响应
                obj = serializer.save()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'result': '新增的那个对象'
                }, status=status.HTTP_201_CREATED)
            else:
                # 校验失败 => 异常响应
                return Response({
                    'status': 1,
                    'msg': serializer.errors,
                }, status=status.HTTP_400_BAD_REQUEST)

    4.反序列化实现单增

    1.数据校验: serializer.is_valid():

    2.数据保存:obj = serializer.save()

    3.错误信息:serializer.errors

        def post(self, request, *args, **kwargs):
            # 单增
            # 1)从请求request中获得前台提交的数据
            # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成)
            # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码)
            # 4)将json数据返回给前台
    
            # 1)将前台请求的数据交给序列化类处理
            # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续
            # 3)序列化组件完成数据入库操作,得到入库对象
            # 4)响应结果给前台
            serializer = serializers.UserModelSerializer(data=request.data)
            if serializer.is_valid():
                # 校验成功 => 入库 => 正常响应
                obj = serializer.save()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'result': '新增的那个对象'
                }, status=status.HTTP_201_CREATED)
            else:
                # 校验失败 => 异常响应
                return Response({
                    'status': 1,
                    'msg': serializer.errors,
                }, status=status.HTTP_400_BAD_REQUEST)

    5.基础校验规则   

    后面练习多体会

    from rest_framework import serializers
    from rest_framework import exceptions
    
    from . import models
    class UserModelSerializer(serializers.ModelSerializer):
        # 自定义反序列化字段(所有校验规则自己定义,也可以覆盖model已有的字段)
        # 覆盖model有的字段,不明确write_only会参与序列化过程
        password = serializers.CharField(min_length=4, max_length=8, write_only=True)
        # 自定义字段,不明确write_only序列化会报错,序列化会从model中强行反射自定义字段,但是model没有对于字段
        re_password = serializers.CharField(min_length=4, max_length=8, write_only=True)
    
    
        class Meta:
            # 该序列化类是辅助于那个Model类的
            model = models.User
            # 设置参与序列化与反序列化字段
            # 插拔式:可以选择性返回给前台字段(插头都是在Model类中制造)
            # fields = ['name', 'age', 'height', 'sex', 'icon]
    
            # 第一波分析:
            # 1)name和age,在fields中标明了,且没有默认值,也不能为空,入库时必须提供,所有校验时必须提供
            # 2)height,在fields中标明了,但是有默认值,所有前台不提供,也能在入库时采用默认值(可以为空的字段同理)
            # 3)password,没有在fields中标明了,所以校验规则无法检测password情况,但是即使数据校验提供了,
            #       也不能完成入库,原因是password是入库的必填字段
            # 4)gender和img是自定义插拔@property字段,默认就不会进行校验(不参与校验)
            # fields = ['name', 'age', 'height', 'gender', 'img']
    
            # 第二波分析:
            # 1)如何区分 序列化反序列化字段 | 只序列化字段(后台到前台) | 只反序列化字段(前台到后台)
            #       不做write_only和read_only任何限制 => 序列化反序列化字段
            #       只做read_only限制 => 只序列化字段(后台到前台)
            #       只做write_only限制 => 只反序列化字段(前台到后台)
    
            # 2)对前台到后台的数据,制定基础的校验规则(了解)
            #       CharField(max_length, min_length, errors_kwargs)
            #       DecimalField(min_value, max_value, max_digits, decimal_places,error_messages)
    
            # 3)如果一个字段有默认值或是可以为空,比如height,如何做限制
            #       虽然有默认值或是可以为空,能不能强制限制必须提供,可以通过required是True来限制
            #       前台提交了该字段,我就校验,没提交我就不校验:1)required是False 2)有校验规则
            fields = ['name', 'age', 'password', 'height', 'gender', 'img', 're_password']
    
            # 第三波分析
            # 1)制定的简易校验规则(没有制定)后,可以再通过字段的 局部钩子 对该字段进行复杂校验
            # 2)每个字段进行逐一复杂校验后,还可以进行集体的 全局钩子 校验
            #       涉及对自定义反序列化字段的校验:re_password(要参与校验,但是不会入库)
    
            # 校验规则
            extra_kwargs = {
                'name': {
                    # 'write_only': True,
                    # 'read_only': True
                },
                'password': {
                    'write_only': True,
                    'min_length': 3,
                    'max_length': 8,
                    'error_messages': {  # 可以被国际化配置替代
                        'min_length': '太短',
                        'max_length': '太长'
                    }
                },
                'height': {
                    # 'required': True,
                    'min_value': 0,
                }
            }

    6.自定义校验规则    全局钩子 局部钩子

    from rest_framework import serializers
    from rest_framework import exceptions
    
    from . import models
    class UserModelSerializer(serializers.ModelSerializer):
        # 自定义反序列化字段(所有校验规则自己定义,也可以覆盖model已有的字段)
        # 覆盖model有的字段,不明确write_only会参与序列化过程
        password = serializers.CharField(min_length=4, max_length=8, write_only=True)
        # 自定义字段,不明确write_only序列化会报错,序列化会从model中强行反射自定义字段,但是model没有对于字段
        re_password = serializers.CharField(min_length=4, max_length=8, write_only=True)
    fields
    = ['name', 'age', 'password', 'height', 'gender', 'img', 're_password']
    # 注:局部全局钩子,是和Meta同缩减,属于序列化类的 # 局部钩子:validate_要校验的字段(self, 要校验的字段值) # 全局钩子:validate(self, 所以字段值的字典) # 校验规则:成功返回传来的数据 | 失败抛出异常 def validate_name(self, value): if 'g' in value.lower(): raise exceptions.ValidationError("这个g不行") else: return value def validate(self, attrs): print(attrs) password = attrs.get('password') # 只是拿出来校验 re_password = attrs.pop('re_password') # 必须取出校验,因为不能入库 if password != re_password: raise exceptions.ValidationError({'re_password': '两次密码不一致'}) else: return attrs

    数据写入

        
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status

    from . import models, serializers

    def post(self, request, *args, **kwargs): # 单增 # 1)从请求request中获得前台提交的数据 # 2)将数据转换成Model对象,并完成数据库入库操作(序列化组件完成) # 3)将入库成功的对象列化成可以返回给前台的json数据(请求与响应数据不对等:请求需要提交密码,响应一定不展示密码) # 4)将json数据返回给前台 # 1)将前台请求的数据交给序列化类处理 # 2)序列化类执行校验方法,对前台提交的所有数据进行数据校验:校验失败就是异常返回,成功才能继续 # 3)序列化组件完成数据入库操作,得到入库对象 # 4)响应结果给前台 serializer = serializers.UserModelSerializer(data=request.data) if serializer.is_valid(): # 校验成功 => 入库 => 正常响应 obj = serializer.save() return Response({ 'status': 0, 'msg': 'ok', 'result': '新增的那个对象' }, status=status.HTTP_201_CREATED) else: # 校验失败 => 异常响应 return Response({ 'status': 1, 'msg': serializer.errors, }, status=status.HTTP_400_BAD_REQUEST)
  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/bigbox/p/12609813.html
Copyright © 2011-2022 走看看