• day02-序列化与反序列化


    序列化器组件

    一 序列化功能的使用

    1 在应用中创建一个py文件,比如叫做serializers.py

    
    
    from rest_framework import serializers
    class StudentSerizlizer(serializers.Serializer):
    ​
        name = serializers.CharField()
        age = serializers.IntegerField()
        class_null = serializers.CharField()
        description = serializers.CharField()

    2 在视图中使用

    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    from students import models
    # Create your views here.
    from django.views import View
    from .serializers import StudentSerizlizer
    ​
    class StudentView(View):
    ​
        def get(self,request):
            # all = models.Student.objects.all()  #quseryset   model
            one = models.Student.objects.get(id=1)  #quseryset   model
            # serializer = StudentSerizlizer(all,many=True)
            # serializer = StudentSerizlizer(all)  #结果为:[{},{}]形式
            serializer = StudentSerizlizer(one)  #得到的结果为字典 data
            print(serializer.data)  #{'name': 'chao', 'age': 18, 'class_null': '31', 'description': 'xxxxx'}
    ​
    ​
            return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
    ​

    3 应用配置文件

    INSTALLED_APPS = [
        ...
        'students.apps.StudentsConfig',
        'rest_framework',
        'ser'
    ]
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'drf01',
            'HOST':'127.0.0.1',
            'PORT':3306,
            'USER':'root',
            'PASSWORD':'123456'
        }
    }
    ​

    二 反序列化功能

    1 创建反序列化组件

    在应用中创建一个py文件,比如叫做serializers.py

    from rest_framework import serializers
    ​
    # 自定义校验函数
    def check666(val):
        if '666' in val:
            raise serializers.ValidationError('不能光喊6666啊,没有用')
        else:
            return val
    ​
    class StudentSerizlizer(serializers.Serializer):
    ​
        name = serializers.CharField(max_length=4,validators=[check666,])
        age = serializers.IntegerField(max_value=18)
        class_null = serializers.CharField()
        # description = serializers.CharField(required=False,allow_null=True)
        # required=False,allow_null=True允许字段为空,也就是不用传递过来这个data
        description = serializers.CharField(allow_blank=True)
        #allow_blank=True 允许只为空字符串

    2 视图中使用

    class Student(View):
        def get..
            ...
            
        def post(self,request):
            # content-type
            # if content-type == 'urlencoded':
            #     #username=chao&password=123&a=1
            #     request.POST['username'] = 'chao'
            # elif content-type == 'form-data':
            #     # 分片接受数据
            #     request.FILES
            # django没有自带解析json数据的解析器,所以需要我们手动的解析,但是drf中已经有了
            # content - type == 'application/json'
            #
            print(request.POST)
            data = {
                'name':request.POST.get('name'),
                'age':request.POST.get('age'),
                'class_null':request.POST.get('class_null'),
                'description':request.POST.get('description'),
            }
    ​
            ser = StudentSerizlizer(data=data)
            print(ser.is_valid())  #校验,全部通过得到True,一个字段错了都是得到False
            print(ser.errors)  #所有字段的错误信息
            
            # print(request.body)
    return HttpResponse('ok')

    三 全局钩子和局部钩子的使用

    class StudentSerizlizer(serializers.Serializer):
        # <QueryDict: {'name': ['c777'], 'age': ['6'], 'description': ['123'], 'class_null': ['1']}>
        name = serializers.CharField(max_length=4,validators=[check666,])
        age = serializers.IntegerField(max_value=18)
        class_null = serializers.CharField()
        # description = serializers.CharField(required=False,allow_null=True)
        # required=False,allow_null=True允许字段为空,也就是不用传递过来这个data
        description = serializers.CharField(allow_blank=True)
        #allow_blank=True 允许只为空字符串
    # 局部钩子:针对单个属性对应的数据进行校验
        def validate_name(self,val):
            # print('xxxxx>>>',val) #xxxxx>>> ccbb
            if '777' in val:
                raise serializers.ValidationError('不能有777')
            return val #如果没有错误,需要return这个属性数据
    # 全局钩子: 主要是针对多个属性数据进行校验
        def validate(self,data): # 是一个字典
            print(data) # OrderedDict([('name', 'c778'), ('age', 6), ('class_null', '1'), ('description', '123')])
            age = data.get('age')
            class_null = data.get('age')
    ​
            if age == class_null:
                raise serializers.ValidationError('age和class——null不能相等')
    ​
            return data  #如果没有错误,全局钩子要return所有数据

    视图部分

      def post(self,request):
            #
            print(request.POST)
            data = {
                'name':request.POST.get('name'),
                'age':request.POST.get('age'),
                'class_null':request.POST.get('class_null'),
                'description':request.POST.get('description'),
            }
    ​
            ser = StudentSerizlizer(data=data)
    ​
            if ser.is_valid():
                
                print(request.body)
                ret = models.Student.objects.create(
                    **ser.validated_data
                )
        
                serializer = StudentSerizlizer(instance=ret)
                print(serializer.data)  #得到的是教研成功之后的所有正确数据
        
        
                return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
            # return JsonResponse({'xx':'xx'})
    else:
                return JsonResponse({'error':'有字段错误'})
     

    执行顺序如下

    # is_valid()方法时,先校验序列化器类中的所有属性Field(CharField(参数))参数对应的校验规则
    # 再执行局部钩子
    # 举例:比如有name和age两个属性,先执行name 的参数校验,在执行name的局部钩子(validate_name(self,val)),然后再执行age属性
    # 的参数校验,再执行age的局部钩子,最后所有属性的参数校验和局部钩子校验完成之后,执行全局钩子
    # 最后执行全局钩子

    常用字段和参数

    常用字段类型

    字段字段构造方式
    BooleanField BooleanField()
    NullBooleanField NullBooleanField()
    CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
    EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
    RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
    SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
    URLField URLField(max_length=200, min_length=None, allow_blank=False)
    UUIDField UUIDField(format='hex_verbose') format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 微软时间戳,通过微秒生成一个随机字符串
    IPAddressField IPAddressField(protocol='both', unpack_ipv4=False, **options)
    IntegerField IntegerField(max_value=None, min_value=None)
    FloatField FloatField(max_value=None, min_value=None)
    DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
    DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
    DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
    TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
    DurationField DurationField()
    ChoiceField ChoiceField(choices) choices与Django的用法相同
    MultipleChoiceField MultipleChoiceField(choices)
    FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
    ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
    ListField ListField(child=, min_length=None, max_length=None)
    DictField DictField(child=)

    选项参数:

    参数名称作用
    max_length 最大长度
    min_length 最小长度
    allow_blank 是否允许为空
    trim_whitespace 是否截断空白字符
    max_value 最大值
    min_value 最小值

    通用参数:

    参数名称说明
    read_only 表明该字段仅用于序列化输出,默认False
    write_only 表明该字段仅用于反序列化输入,默认False
    required 表明该字段在反序列化时必须输入,默认True
    default 反序列化时使用的默认值
    allow_null 表明该字段是否允许传入None,默认False
    validators 该字段使用的验证器
    error_messages 包含错误编号与错误信息的字典
    label 用于HTML展示API页面时,显示的字段名称
    help_text 用于HTML展示API页面时,显示的字段帮助提示信息

    is_valid 中参数 raise_exception参数

    等于True会主动抛异常

    serializer.is_valid(raise_exception=True)

    保存数据

    方式1  直接在视图中保存
     if ser.is_valid():
    
                # print(request.body)
                ret = models.Student.objects.create(
                    **ser.validated_data
                )
                
                serializer = StudentSerizlizer(instance=ret)
    
                return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
    
            else:
                print(ser.errors)
                return JsonResponse({'error':'有字段错误'})
    方式2
    在序列化器中定义create方法来数据的保存
    class StudentSerizlizer(serializers.Serializer):
        # <QueryDict: {'name': ['c777'], 'age': ['6'], 'description': ['123'], 'class_null': ['1']}>
        name = serializers.CharField(max_length=4,validators=[check666,])
         ...
        
        def create(self, validated_data):
    
            # self.validated_data
            # validated_data
            # print('>>',self.validated_data)
            print('>>',validated_data)
            ret = models.Student.objects.create(
                **validated_data
            )
            return ret
    视图中通过save方法来触发,序列化器类中的create方法
    if ser.is_valid():
    
                instance = ser.save()  #得到create方法的返回值
                serializer = StudentSerizlizer(instance=instance)
    
                return JsonResponse(serializer.data,safe=False,json_dumps_params={'ensure_ascii':False})
                # return JsonResponse({'xx':'xx'})

    更新数据

    在序列化器中定义update方法来数据的更新
    class StudentSerizlizer(serializers.Serializer):
        # <QueryDict: {'name': ['c777'], 'age': ['6'], 'description': ['123'], 'class_null': ['1']}>
        name = serializers.CharField(max_length=4,validators=[check666,])
         ...
        # 做更新动作
        def update(self, instance, validated_data):
    
            # print(instance)
            # print(validated_data)     
    视图
       def put(self,request):
    
            data = {
                'id': 2,
                'name':'xx',
                'age':8,
                'sex':0,
                'class_null':'9',
                'description':'xx',
    
            }
            obj = models.Student.objects.get(id=data.get('id'))
            s_obj = StudentSerizlizer(instance=obj,data=data)  # 实例化序列化器类时,传入instance参数
            if s_obj.is_valid():
                s_obj.save()  #触发序列化器类的update方法
    
            else:
                return JsonResponse({'error':'数据错误'})
        
    read_only和write_only参数的区别
    from rest_framework import serializers
    
    class StudentSerizlizer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        # read_only=True,序列化时序列化出该字段数据,反序列化校验时不要校验这个数据
        name = serializers.CharField(max_length=4,)
    
        age = serializers.IntegerField(max_value=18,write_only=True)
        # write_only=True,序列化时不序列化这个字段数据,反序列校验时,需要客户端传递这个数据过来进行校验
        class_null = serializers.CharField()
    
        description = serializers.CharField(allow_blank=True)

    视图部分

    def put(self,request):
            data = {
                'name':'chao',
                'age':18
            }
            serializer = StudentSerizlizer(data=data,partial=True)
            # partial=True:只需要校验传入给序列化器的数据,适用于部分数据更新
            serializer.is_valid()
            print(serializer.errors)
            print('正确数据:', serializer.validated_data)
            
            return JsonResponse({'ss': 'kk'})

    modelSerializer的使用

    序列化和反序列化的使用

    定义如下的类

    from rest_framework import serializers
    from students import models
    class MmModelSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Student
            # fields = '__all__'
            fields = ['id','name','age'] # 序列化表中的数据
            # exclude = ['name', 'age'] # 序列化除这些的其他数据
            # 增加额外校验参数
            extra_kwargs = {
                'id':{'read_only': True},
                'name': {'max_length': 6}
            }
    
            '''
                id
                name = models.CharField(max_length=100,verbose_name="姓名",help_text='提示文本:不能为空')
                sex = models.BooleanField(default=1,verbose_name="性别")
                age = models.IntegerField(verbose_name="年龄")
                class_null = models.CharField(max_length=5,verbose_name="班级编号")
                description = models.TextField(max_length=1000,verbose_name="个性签名")
            
            '''
            '''
                    id = serializers.IntegerField(read_only=True)
                    name = serializers.CharField(max_length=6,)  # name char(6)
                    age = serializers.IntegerField(max_value=18,write_only=True)
                    sex = serializers.BooleanField()
                    class_null = serializers.CharField()
                    description = serializers.CharField(allow_blank=True)
            
            '''

    视图当中使用

    obj.save() # 自动能够帮我们进行数据保存,不需要creat方法

    from django.shortcuts import render
    from django.http import JsonResponse
    # Create your views here.
    from django.views import View
    from .serializers import StudentModelSerializer
    from students import models
    class StudentView(View):
    
        def get(self,request):
            all = models.Student.objects.all()
    
            model_ser = StudentModelSerializer(instance=all,many=True)
            print()
    
            return JsonResponse(model_ser.data, safe=False, json_dumps_params={'ensure_ascii':False})
    
        def post(self,request):
            print(request.POST)
            obj = StudentModelSerializer(data=request.POST)
    
            if obj.is_valid():
                print(obj.validated_data)
                obj.save()  # 自动能够帮我们进行数据保存,不需要creat方法
                return JsonResponse({'msg':'success'})
            print(obj.errors)
            print(obj.validated_data)
            return JsonResponse({'xx':'ssssss'})

    modelserializer进行数据保存时的问题

    视图相关

    APIView类

    request对象

    from rest_framework.views import APIView
    
    class UserView(APIView):
    
        def get(self,request):
            print(request.GET)
            print(request.query_params)
            # request.GET和request.query_params是等价的
    
            return JsonResponse({'xx':'xxxxx'})
    
    
    
        def post(self,request):
            print(request)
            # 当发送的数据格式为..urlencoded类型时,request.POST和request.data等价
            # print(request.POST.getlist('hobby')) #<QueryDict: {'name': ['小林2'], 'age': ['6']}>
            # 当发送过来的是json类型数据时,我们使用request.data属性能够获取到数据
            print(request.data) #{'username': 'xxxx', 'password': '123'},普通字典类型
            # request.data能够获取到客户端发送过来的json类型数据,但是得到的结果为普通字典类型,但是如果是多选数据,不能使用getlist方法获取
    
            return JsonResponse({'xx': 'xxxxx'})
    response对象
    查看drf的默认配置
    from rest_framework import settings
    引入response
    from rest_framework.response import Response
    Response默认响应的是json数据类型
    
    当用浏览器访问时看到页面效果.
    from rest_framework import settings
    用户配置替换drf内部配置的写法
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
            'rest_framework.renderers.JSONRenderer',  # json渲染器
            'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览器API渲染器
        )
    }

    response的方法的相关参数

    Response(data, status=None, template_name=None, headers=None, content_type=None)

    响应状态码

    from rest_framework import status
    
    # return Response({'xx':'xxxxx'}, status=201)
    return Response({'xx':'xxxxx'}, status=status.HTTP_201_CREATED)

    所有状态码

    HTTP_100_CONTINUE = 100
    HTTP_101_SWITCHING_PROTOCOLS = 101
    HTTP_200_OK = 200
    HTTP_201_CREATED = 201
    HTTP_202_ACCEPTED = 202
    HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
    HTTP_204_NO_CONTENT = 204
    HTTP_205_RESET_CONTENT = 205
    HTTP_206_PARTIAL_CONTENT = 206
    HTTP_207_MULTI_STATUS = 207
    HTTP_208_ALREADY_REPORTED = 208
    HTTP_226_IM_USED = 226
    HTTP_300_MULTIPLE_CHOICES = 300
    HTTP_301_MOVED_PERMANENTLY = 301
    HTTP_302_FOUND = 302
    HTTP_303_SEE_OTHER = 303
    HTTP_304_NOT_MODIFIED = 304
    HTTP_305_USE_PROXY = 305
    HTTP_306_RESERVED = 306
    HTTP_307_TEMPORARY_REDIRECT = 307
    HTTP_308_PERMANENT_REDIRECT = 308
    HTTP_400_BAD_REQUEST = 400
    HTTP_401_UNAUTHORIZED = 401
    HTTP_402_PAYMENT_REQUIRED = 402
    HTTP_403_FORBIDDEN = 403
    HTTP_404_NOT_FOUND = 404
    HTTP_405_METHOD_NOT_ALLOWED = 405
    HTTP_406_NOT_ACCEPTABLE = 406
    HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
    HTTP_408_REQUEST_TIMEOUT = 408
    HTTP_409_CONFLICT = 409
    HTTP_410_GONE = 410
    HTTP_411_LENGTH_REQUIRED = 411
    HTTP_412_PRECONDITION_FAILED = 412
    HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
    HTTP_414_REQUEST_URI_TOO_LONG = 414
    HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
    HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
    HTTP_417_EXPECTATION_FAILED = 417
    HTTP_418_IM_A_TEAPOT = 418
    HTTP_422_UNPROCESSABLE_ENTITY = 422
    HTTP_423_LOCKED = 423
    HTTP_424_FAILED_DEPENDENCY = 424
    HTTP_426_UPGRADE_REQUIRED = 426
    HTTP_428_PRECONDITION_REQUIRED = 428
    HTTP_429_TOO_MANY_REQUESTS = 429
    HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
    HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
    HTTP_500_INTERNAL_SERVER_ERROR = 500
    HTTP_501_NOT_IMPLEMENTED = 501
    HTTP_502_BAD_GATEWAY = 502
    HTTP_503_SERVICE_UNAVAILABLE = 503
    HTTP_504_GATEWAY_TIMEOUT = 504
    HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
    HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
    HTTP_507_INSUFFICIENT_STORAGE = 507
    HTTP_508_LOOP_DETECTED = 508
    HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
    HTTP_510_NOT_EXTENDED = 510
    HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511

    template_name,用于自定制浏览器的响应页面,了解

    headers定制响应头键值对

     return Response({'xx':'xxxxx'}, status=status.HTTP_201_CREATED,headers={'xx':'oo'})
  • 相关阅读:
    URL记录
    Mongodb集群节点故障恢复场景分析(转)
    IO 和 NIO 的区别
    VUE 前端项目优化方法
    缓存的穿透和雪崩
    接口如何处理重复请求?
    线程池构造类 ThreadPoolExecutor 的 5 个参数
    大型网站在架构上应当考虑哪些问题
    synchronized 和 lock 的区别
    JVM虚拟机 YGC和FGC发生的具体场景
  • 原文地址:https://www.cnblogs.com/wgwg/p/13880759.html
Copyright © 2020-2023  润新知