zoukankan      html  css  js  c++  java
  • 2. 序列化器-Serializer

     本节内容

      一、前言

      二、序列化器的作用

      三 、定义序列化器

         四 、创建Serializer对象

      五、序列化器的使用

        5.1 序列化

        5.2 反序列化

        5.3  反序列化校验方式补充

        5.4  常用通用参数功能介绍

        5.5 保存数据(添加、更新)

         5.6 附加说明

      六、模型类序列化器

        6.1  定义

        6.2  定义局部钩子和全局钩子

        6.3  查询 、增加、更改

     

     

    一、前言

    在没有使用序列化器之前从数据库取出数据并发送给前端的流程如下。json是不能直接序列化Queryset类型的数据的

    from django.views import View
    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    class StudentsView(View):
        # 查询所有人员信息的接口
        def get(self,request):
            students = models.Student.objects.all().values()
            # queryset[{1,'老白','1','33','很骚'},{}]
    
            # 前端小姐姐  需要-- [{},{},]
            
            # 强制将queryset 类型转化成列表
            data = list(students)
    
            #  方式 2  使用JsonResponse 
            # 如果data是一个非字典数据,那么还需要在JsonResponse中加一个参数safe=False,如果是字典数据,就不需要加这个参数了
            return JsonResponse(data, safe=False,json_dumps_params={'ensure_ascii': False})
           
            #  方式 1 使用HttpResponse 需要我们自己序列化
            # import json
            # data_json = json.dumps(data, ensure_ascii=False)
            # return HttpResponse(data_json)
        
    View Code

    二、序列化器的作用

    取出如果Queryset数据(all()取出的)是多条的 ,打印出是列表中的元素是模型类对象的格式,那么通过序列化后的多条数据是列表中的元素是字典的格式

    取出如果Queryset数据是(get()或者filter().first())单条的 ,打印出是模型类对象的格式,那么通过序列化后的数据是字典的格式

     filter()取出的为 [OrderedDict([('id', 1), ('name', 'laobai'), ('age', 18), ('sex', True)])]

    1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
    2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
    3. 反序列化,完成数据校验功能

    三 、定义序列化器

    Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

    接下来,为了方便演示序列化器的使用,我们先创建一个新的子应用sers

    python manage.py startapp sers

    我们已有了一个数据库模型类students/Student

    from django.db import models
    
    # Create your models here.
    class Student(models.Model):
        # 模型字段
        name = models.CharField(max_length=100,verbose_name="姓名",help_text="提示文本:账号不能为空!")
        sex = models.BooleanField(default=True,verbose_name="性别")
        age = models.IntegerField(verbose_name="年龄")
        class_null = models.CharField(max_length=5,verbose_name="班级编号")
        description = models.TextField(verbose_name="个性签名")
    
        class Meta:
            db_table="tb_student"
            verbose_name = "学生"
            verbose_name_plural = verbose_name
    View Code

    我们想为这个模型类提供一个序列化器,可以定义如下:

    from rest_framework import serializers
    
    # 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
    # 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化
    class StudentSerializer(serializers.Serializer):
        """学生信息序列化器"""
        # 1. 需要进行数据转换的字段
        id = serializers.IntegerField()  # 序列化后为整形
        name = serializers.CharField() # 序列化为字符串
        age = serializers.IntegerField()  
        sex = serializers.BooleanField()   # 转化为布尔型
        description = serializers.CharField()
    

    注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

    常用字段类型

    字段字段构造方式
    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页面时,显示的字段帮助提示信息

    四 、创建Serializer对象

    定义好Serializer类后,就可以创建Serializer对象了。

    Serializer的构造方法

    Serializer(instance=None, data=empty, **kwarg)

    说明:

    1)用于序列化时,将模型类对象传入instance参数

    2)用于反序列化时,将要被反序列化的数据传入data参数

    3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

    serializer = AccountSerializer(account, context={'request': request})

    通过context参数附加的数据,可以通过Serializer对象的context属性获取。

    1. 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。

    2. 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。

    3. 序列化器的字段声明类似于我们前面使用过的表单系统。

    4. 开发restful api时,序列化器会帮我们把模型数据转换成字典.

    5. drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.

    五、序列化器的使用

    序列化器的使用分两个阶段:

    1. 在客户端请求时,使用序列化器可以完成对数据的反序列化。

    2. 在服务器响应时,使用序列化器可以完成对数据的序列化

    5.1 序列化

    1、序列化返回值获取其data属性可以得到序列化后的数据

    2、序列化多条数据时 ,参数上要加 many=True

    3、通过序列化的数据必须是模型类对象

    students = models.Student.objects.all()
    print(students)
    # 序列化的是多条记录对象,需要加many=True的参数
    serialiezr_obj = StudentsSerializers(instance=students, many=True)
    
    # 序列化单条数据
    # student = models.Student.objects.all().get(id=1)
    # 单条数据必须是模型类对象到格式
    # student = models.Student.objects.filter(id=1).first()
    # print(student)
    # serialiezr_obj = StudentsSerializers(instance=student)
    
    #取出序列化的后的数据
    data = serialiezr_obj.data
    from django.http import JsonResponse
    
    # Create your views here.
    from django.views import View
    from app01 import models
    from .serializers import StudentsSerializers
    from unser.serializers import Students2Serializers
    class StudentsView(View):
        # 查询所有人员信息的接口
    
        def get(self,request):
            # 序列化多条记录对象
            students = models.Student.objects.all()
            print(students)
            # 序列化的是多条记录对象,需要加many=True的参数
            serialiezr_obj = StudentsSerializers(instance=students, many=True)
    
            # 序列化单条数据
            # student = models.Student.objects.all().get(id=1)
            # 单条数据必须是模型类对象到格式
            # student = models.Student.objects.filter(id=1).first()
            # print(student)
            # serialiezr_obj = StudentsSerializers(instance=student)
    
            #取出序列化的后的数据
            data = serialiezr_obj.data
            print(data)
            # return HttpResponse('ok')
            # return JsonResponse(data, safe=False, json_dumps_params={'ensure_ascii': False})
            return JsonResponse(data, json_dumps_params={'ensure_ascii': False})
    View Code

    5.2 反序列化

    使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

    在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

    验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

    验证成功,可以通过序列化器对象的validated_data属性获取数据。

    在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

    为了方便演示效果,我们单独再次创建一个子应用unsers,

    python manage.py startapp unsers

    定义序列化器,代码

    from rest_framework import serializers
    class StudentSerializer(serializers.Serializer):
        # 需要转换的字段声明
        # 小括号里面声明主要提供给反序列化使用的
        name = serializers.CharField(required=True, max_length=20)
        age = serializers.IntegerField(max_value=150, min_value=0,required=True)
        sex = serializers.BooleanField(default=True)
        description = serializers.CharField(required=False,allow_null=True, allow_blank=True) 

       #required=False,字段都可以不传递给后端,allow_null=True,允许提交过来的数据为空值(null--None),allow_blank=True 允许提交过来的数据为空字符串

    通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证

    POST请求的两种编码格式:
    application/x-www-urlencoded:是浏览器默认的编码格式,用于键值对参数,参数之间用&间隔;Django中可以用request.post取出数据
    multipart/form-data:常用于文件等二进制,也可用于键值对参数,最后连接成一串字符传输。Django中 的文件取出用
    request.FILES[file] = 文件数据,其余用 request.post取出数据
    application/json : POST请求发送json格式 request.post取出为空 ,只能用 request.body转码 反序列化成字典 ,DRF中主要用request.data取出数据
    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    
    # Create your views here.
    from django.views import View
    from app01 import models
    from .serializers import StudentsSerializers
    from unser.serializers import Students2Serializers
    class StudentsView(View):
         def post(self,request):
    
            # content-type == 'application/json'
    
            data = request.POST
            print(request.body)
            a = request.body.decode()
            import json
            data = json.loads(a)
            print('>>>', data)
    
            # {'name': 'chao', 'age': 9, 'sex': 0, 'class_null': '33', 'description': 'xxxxx'}
    
            """
            # django的数据解析组件做的事情
            if content-type == 'xxxx_urlencoded':
                a=1&b=2
                requset.POST[a] = 1
                requset.POST[b] = 2
            elif content-type == 'mutiple_part/form-data'
                input type="file" name='file'
                
                request.FILES[file] = 文件数据
                request.POST[a] = 1
            elif content-type == 'application/json':
                啥也没做
                
            """
    
            print(data)  # <QueryDict: {}>
    
    
            serializer_obj = Students2Serializers(data=data)
            # serializer_obj.is_valid()  # 触发校验功能,但凡是有一个数据不满足我们序列器的条件,那么就返回一个False,如果够通过了,那么返回True
            if serializer_obj.is_valid():
                # 保存数据
                print('正确数据>>>',serializer_obj.validated_data) # validated_data拿到的是所有通过校验的正确数据
                # 保存数据
    
                return HttpResponse('ok')
            else:
                # {}  但凡有错误,serializer_obj.validated_data是空的
                print('>>>>', serializer_obj.validated_data)
    
                print(serializer_obj.errors)  # errors存储的都是校验之后的所有错误信息
                return HttpResponse('not ok')
    # Create your views here.
    from django.http import JsonResponse
    from django.views import View
    from .serializers import StudentSerializer
    from students.models import Student
    class StudentView(View):
        def post(self,request):
            """添加一个学生"""
            # 接受参数,没用application/json 传送数据
            post_data = request.POST
            data = {
                "name":post_data.get('name'),
                "age":post_data.get('age'),
                "sex":post_data.get('sex'),
                "description":post_data.get('description'),
            }
            # 调用序列化器进行反序列化验证和转换
            serializer = StudentSerializer(data=data)
                    #serializer.errors  #查看错误信息
            
            # 当验证失败时,可以直接通过声明 raise_exception=True 让django直接跑出异常,那么验证出错之后,直接就再这里报错,程序中断了就
            
            result = serializer.is_valid(raise_exception=True)
            print( "验证结果:%s" % result )
    
            # 获取通过验证后的数据
            print( serializer.validated_data ) # form -- clean_data
            # 保存数据
            student = Student.objects.create(
                name=serializer.validated_data.get("name"),
                age=serializer.validated_data.get("age"),
                sex=serializer.validated_data.get("sex")
            )
    
            print(student)
            # 返回响应结果给客户端
            # alt + enter,可以实现快速导包
            return JsonResponse({"message": "ok"})
    反序列化中记住的要点

    is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应

    # Return a 400 response if the data was invalid.
    serializer.is_valid(raise_exception=True)

    5.3  反序列化校验方式补充

    顺序: 先校验参数约束 -- 局部钩子 -- 全局钩子

    5.3.1  validators 自定义校验函数

    在字段中添加validators选项参数,也可以补充验证行为,如

    def check_age(age):
        if age ==50:
            raise serializers.ValidationError("年龄不能刚好是50")
        return age
    
    class StudentSerializer(serializers.Serializer):
        # 需要转换的字段声明
        # 小括号里面声明主要提供给反序列化使用的
        name = serializers.CharField(required=True, max_length=20)
        age = serializers.IntegerField(max_value=150, min_value=0,required=True,validators=[check_age])
        sex = serializers.BooleanField(default=True)
        description = serializers.CharField(required=False,allow_null=True, allow_blank=True)

    5.3.2 局部钩子  validate_字段名

    <field_name>字段进行验证,如

    class StudentSerializer(serializers.Serializer):
        """学生数据序列化器"""
        ...
    
        # 序列化器中可以自定义单个字段的验证方法  def validate_<字段名>(用户提交的字段数据):
        def validate_name(self,data):
            if(data=="老男孩"):
                raise serializers.ValidationError("用户名不能是老男孩")
    
            # 验证完成以后务必要返回字段值
            return data

    5.3.3 全局钩子  validate

    在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如

    class StudentSerializer(serializers.Serializer):
        """学生数据序列化器"""
        ...
            
        # 方法名时固定的,用于验证多个字段,参数就是实例化序列化器类时的data参数
        def validate(self,data):
            name = data.get("name")
            if(name == "python"):
                raise serializers.ValidationError("用户名不能是python")
    
            age = data.get("age")
            if(age==0):
                raise serializers.ValidationError("年龄不能是0")
    
            # 验证完成以后务必要返回data
            return data

    5.4  常用通用参数功能介绍

    read_only:在序列化阶段会加工出来这个数据,反序列化阶段验证用户提交的数据时,会自动忽略这个数据,不对这个数据进行校验
    write_only: 相反,反序列化阶段会校验这个数据,序列化阶段不会将这个字段数据加工出来
    error_meeage : 当不符和校验要求时,抛出的中文提示 键为校验名字的关键字,
     
    class StudentsSerializers(serializers.Serializer):
        # read_only  -- write_only
        id = serializers.IntegerField(read_only=True)
        # read_only:在序列化阶段会加工出来这个数据,反序列化阶段验证用户提交的数据时,会自动忽略这个数据,不对这个数据进行校验
        # write_only: 相反,反序列化阶段会校验这个数据,序列化阶段不会将这个字段数据加工出来
        name = serializers.CharField(write_only=True,error_messages={'required': 'name字段必填'})
        age = serializers.IntegerField(min_value=10, error_messages={'min_value':'最短不能短过10cm', 'required': 'age字段必填'})
        sex = serializers.BooleanField()
        # 如果没有定义下面两个字段,那么反序列化阶段进行数据校验时,校验成功的数据中就不会有这两个字段的数据
        class_null = serializers.CharField()
        # description = serializers.CharField(validators=[check_666,check_555],)
        # validators自定义校验函数
        description = serializers.CharField(validators=[check_666, ],)

    5.5 保存数据(添加、更新)

     5.5.1 方式一

    前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象.

    首先我们可以在views中直接写上保存数据的代码

    from django.shortcuts import render, HttpResponse
    from django.http import JsonResponse
    
    # Create your views here.
    from django.views import View
    from app01 import models
    from .serializers import StudentsSerializers
    
    
    class StudentsView(View):
        ##更新数据
        def post(self, request):
    
            # content-type == 'application/json'
            data = request.POST
            print(request.body)
            a = request.body.decode()
            import json
            data = json.loads(a)
            print('>>>', data)
            serializer_obj = StudentsSerializers(data=data)
            if serializer_obj.is_valid():
                # 保存数据
                print('正确数据>>>', serializer_obj.validated_data)  # validated_data拿到的是所有通过校验的正确数据
                # 保存数据
                # 方式1: 直接通过orm对正确数据进行校验
                new_obj = models.Student.objects.create(**serializer_obj.validated_data)
    
                # restful api接口规范要求,添加记录成功之后,需要将添加的这条记录返回给客户端{},
                # 序列化的参数: instance
                # 反序列化的参数: data
                serializer_obj = StudentsSerializers(instance=new_obj)
    
                return JsonResponse(serializer_obj.data)
            else:
                # {}  但凡有错误,serializer_obj.validated_data是空的
                print('>>>>', serializer_obj.validated_data)
    
                print(serializer_obj.errors)  # errors存储的都是校验之后的所有错误信息
                return HttpResponse('not ok')
    
        # 修改记录
        def put(self, request):
    
            d1 = {
                'name': '老白',
                'age': 20,
                'sex': 1,
                # 'class_null':'33',
                'description': 'xxxxxx'
    
            }
            id = 1
            students = models.Student.objects.filter(id=id)
            # s_obj = StudentsSerializers(data=d1)
    
            s_obj = StudentsSerializers(instance=students.first(), data=d1)
    
            if s_obj.is_valid():
                # 修改记录
                print(s_obj.validated_data)
    
                # 方式1: 直接orm更新
                students.update(
                    **s_obj.validated_data
                )
               
                # 更新完之后,也要返回整条记录{}
                obj = StudentsSerializers(instance=students.first())
    
                return JsonResponse(obj.data)
            else:
                print(s_obj.errors)
                return HttpResponse('not ok!!!')
    代码

     5.5.2 方式二

    还可以通过序列化器提供的create()和update()两个方法来实现。

    from app01 import models
    from rest_framework import serializers
    def check_666(val):  #val -- description字段数据
    
        if '666' in val:
            raise serializers.ValidationError('不能光喊6,木有用')
        else:
            return val
    
    class StudentsSerializers(serializers.Serializer):
        # read_only  -- write_only
        id = serializers.IntegerField(read_only=True)
        # read_only:在序列化阶段会加工出来这个数据,反序列化阶段验证用户提交的数据时,会自动忽略这个数据,不对这个数据进行校验
        # write_only: 相反,反序列化阶段会校验这个数据,序列化阶段不会将这个字段数据加工出来
    
        name = serializers.CharField(write_only=True,error_messages={'required': 'name字段必填'})
    
        age = serializers.IntegerField(min_value=10, error_messages={'min_value':'最短不能短过10cm', 'required': 'age字段必填'})
    
        sex = serializers.BooleanField()
        # 如果没有定义下面两个字段,那么反序列化阶段进行数据校验时,校验成功的数据中就不会有这两个字段的数据
        class_null = serializers.CharField()
        # description = serializers.CharField(validators=[check_666,check_555],)
        # validators自定义校验函数
        description = serializers.CharField(validators=[check_666, ],)
    
    
        def create(self, validated_data):
            #create--validated_data {'name': '佳庆', 'age': 11, 'sex': False, 'class_null': '33', 'description': 'xxxx'}
            print('create--validated_data',validated_data)
            obj = models.Student.objects.create(
                **validated_data
            )
    
            return obj
    
        def update(self, instance, validated_data):
            '''
            :param instance:   实例化序列化器类时传递的模型类对象students.first()
            :param validated_data:  校验成功之后的数据
            :return:
            '''
            print('self.context',self.context)
            # self.context {'request': <WSGIRequest: PUT '/unser/students/'>}
    
            instance.name = validated_data.get('name')
            instance.age = validated_data.get('age')
            instance.sex = validated_data.get('sex')
            instance.class_null = validated_data.get('class_null')  # None
            instance.description = validated_data.get('description')
            instance.save()
    
            return instance
    View Code

    实现了上述两个方法后,在视图中调用序列化器进行反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了

    student = serializer.save()  #如果是添加,自动会调用create,更新就自动调用update
    from django.shortcuts import render, HttpResponse
    from django.http import JsonResponse
    
    # Create your views here.
    from django.views import View
    from app01 import models
    from .serializers import StudentsSerializers
    
    
    class StudentsView(View):
        ##更新数据
        def post(self, request):
    
            # content-type == 'application/json'
            data = request.POST
            print(request.body)
            a = request.body.decode()
            import json
            data = json.loads(a)
            print('>>>', data)
            serializer_obj = StudentsSerializers(data=data)
            if serializer_obj.is_valid():
                # 保存数据
                print('正确数据>>>', serializer_obj.validated_data)  # validated_data拿到的是所有通过校验的正确数据
                # 保存数据
                # 方式2: 调用save方法
                new_obj = serializer_obj.save()  # -- 触发序列器类中的create方法
    
                # restful api接口规范要求,添加记录成功之后,需要将添加的这条记录返回给客户端{},
                # 序列化的参数: instance
                # 反序列化的参数: data
                serializer_obj = StudentsSerializers(instance=new_obj)
    
                return JsonResponse(serializer_obj.data)
            else:
                # {}  但凡有错误,serializer_obj.validated_data是空的
                print('>>>>', serializer_obj.validated_data)
    
                print(serializer_obj.errors)  # errors存储的都是校验之后的所有错误信息
                return HttpResponse('not ok')
    
        # 修改记录
        def put(self, request):
    
            d1 = {
                'name': '老白',
                'age': 20,
                'sex': 1,
                # 'class_null':'33',
                'description': 'xxxxxx'
    
            }
            id = 1
            students = models.Student.objects.filter(id=id)
            # s_obj = StudentsSerializers(data=d1)
    
            s_obj = StudentsSerializers(instance=students.first(), data=d1)
    
            if s_obj.is_valid():
                # 修改记录
                print(s_obj.validated_data)
                # 方式2: save方法更新
                # 当实例化序列化器类的对象时,如果传递了instance参数,那么save方法会自动触发序列化器类的update方法,如果没有传,那么会自动触发create方法
                s_obj.save()
                # 更新完之后,也要返回整条记录{}
                obj = StudentsSerializers(instance=students.first())
                return JsonResponse(obj.data)
            else:
                print(s_obj.errors)
                return HttpResponse('not ok!!!')
    视图代码

     5.6 附加说明

     1、 在视图函数中想要传递传递额外参数给序列化器类 

     视图函数中的引用

    serializer = StudentsSerializers(instance=students.first(),data=d1, context={'request': request, 'a':'b'})

    序列化器类如在函数 update中 用法

       
    def update(self, instance, validated_data): ''' :param instance: 实例化序列化器类时传递的模型类对象students.first() :param validated_data: 校验成功之后的数据 :return: ''' print('self.context',self.context) # self.context {'request': <WSGIRequest: PUT '/unser/students/'>} instance.name = validated_data.get('name') instance.age = validated_data.get('age') instance.sex = validated_data.get('sex') instance.class_null = validated_data.get('class_null') # None instance.description = validated_data.get('description') instance.save() return instance

     2、默认序列化器必须传递所有required的字段,否则会抛出验证异常。但是我们可以使用partial参数请求通过

    partial=True:  即便是有些字段是必须校验的字段,如果客户端没有传递过来这个数据,也是能够通过校验的,
    --- 部分字段数据更新(可以做到不需要传递所有序列化器类要求的必须参数数据)

     用户只更新部分字段,加上参数后可以传递部分字段,通过序列化器

    # 更新学生的部分字段信息,当数据库允许为空,但是序列化器要求必须字段填写的时候,可以使用以下方式避开
    serializer = StudentSerializer(instance=instance, data=data, partial=True)

     六、模型类序列化器

    如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

    ModelSerializer与常规的Serializer相同,但提供了:

    • 基于模型类自动生成一系列字段

    • 基于模型类自动为Serializer生成validators,比如unique_together

    • 包含默认的create()和update()的实现

     6.1  定义

     比如我们创建一个StudentModelSerializer

    from rest_framework import serializers

    class
    StudentModelSerializer(serializers.ModelSerializer): # id = serializers.IntegerField(read_only=True) class Meta: model = models.Student fields = '__all__' # # 表示操作模型中的所有字段 # fields = ['name', 'class_null'] # 只用某些字段 # exclude = ['id','name'] 排除某些字段 # 给字段添加额外约束参数的时候用的 extra_kwargs = { 'id': {'read_only':True}, 'age': {'write_only':True, 'min_value':10}, 'name': { 'error_messages':{ 'required': 'name不能为空', # 定制错误信息 } } }

          # 验证代码

          # 也可以重新声明一个create和update

     
    • model 指明参照哪个模型类

    • fields 指明为模型类的哪些字段生成

     6.2  定义局部钩子和全局钩子

    局部钩子和全局钩子的使用和基础序列化器类时一样的
    class StudentModelSerializer(serializers.ModelSerializer):
        # id = serializers.IntegerField(read_only=True)
        class Meta:
            model = models.Student
            fields = '__all__'  # # 表示操作模型中的所有字段
            # fields = ['name', 'class_null']  # 只用某些字段
            # exclude = ['id','name'] 排除某些字段
            # 给字段添加额外约束参数的时候用的
            extra_kwargs = {
                'id': {'read_only':True},
                'age': {'write_only':True, 'min_value':10},
                'name': {
                    'error_messages':{
                        'required': 'name不能为空', # 定制错误信息
                    }
                }
            }
    
        # 局部钩子和全局钩子的使用和基础序列化器类时一样的
        def validate(self, attrs):
            # model序列化器类中的全局钩子 OrderedDict([('name', '佳庆3'), ('sex', False), ('age', 11), ('class_null', '33'), ('description', 'xxxx')])
            print('model序列化器类中的全局钩子',attrs)
    
            return attrs

    6.3  查询 、增加、更改

    模型类序列化器中有create和update,直接save() 即可保存 也可以根据情况 重新声明一个create和update

    注意:instance是新增或者更新的那条记录的模型类对象

     instance = s_obj.save()  # 直接就保存了
      # instance是新增或者更新的那条记录的模型类对象
    from ser.serializers import StudentModelSerializer
    class StudentModelView(View):
    
        def get(self,request):
            students = models.Student.objects.all()
            s_obj = StudentModelSerializer(instance=students,many=True)
            return JsonResponse(s_obj.data, safe=False)
    
    
        def post(self,request):
            # data = request.POST
            print(request.body)
            a = request.body.decode()
            import json
            data = json.loads(a)
            print('>>>', data)
    
            s_obj = StudentModelSerializer(data=data)
            if s_obj.is_valid():
                instance = s_obj.save()  # 直接就保存了
                # instance是新增或者更新的那条记录的模型类对象
    
                return HttpResponse('ok')
            else:
                print('error???',s_obj.errors)
                return HttpResponse('not ok ---')
    
        def put(self,request):
            d1 = {
                'name': '老白2',
                'age': 202,
                'sex': 1,
                # 'class_null':'33',
                'description': 'xxxxxx'
    
            }
            id = 1
            old_obj =  models.Student.objects.get(id=id)
            s_obj = StudentModelSerializer(data=d1,instance=old_obj,partial=True)
            if s_obj.is_valid():
                s_obj.save()  #--更新保存
                return HttpResponse('ok')
            else:
                print(s_obj.errors)
                return HttpResponse('not ok')
    视图中的增查改函数

     

  • 相关阅读:
    Firefox浏览器安装 Disable Javascript插件
    Web常见漏洞及修复建议
    查询公网出口IP
    jQuery jsonp跨域请求--转载自https://www.cnblogs.com/chiangchou/p/jsonp.html
    理解闭包 js回收机制--转载https://www.cnblogs.com/wangyingblog/p/5569745.html
    全面理解Javascript闭包和闭包的几种写法及用途--转载自https://www.cnblogs.com/yunfeifei/p/4019504.html
    什么是闭包?闭包的优缺点?--转载自https://www.cnblogs.com/cxying93/p/6103375.html
    JavaScript局部变量和全局变量的理解--转载自https://www.cnblogs.com/eric-qin/p/4166552.html
    好文收藏
    SQL In和Like 参数化
  • 原文地址:https://www.cnblogs.com/yj0405/p/14570404.html
Copyright © 2011-2022 走看看