• DRF 2 序列化器


    2 序列化器

    作用

    1. 序列化,把模型对象转换成字典

      因为def规范要求response需要返回json格式数据,但是查表得到的是一个表模型对象,而python中对象不能被json序列化,所以需要将对象转成字典(手动实现:一个个取对象的属性用for生成字典)再用response处理(内部自动序列后)返回json格式数据

    2. 反序列化 把字典格式的数据写入表模型中

      客户端发送过来的数据,经过request处理后得到一个字典,虽然用**将字典传入可以快速写入数据,但是写入之前先要判断k与字段名知否对应,序列化器则简化了这两个步骤.

    2.1 半自动序列化器 Serializer

    from rest_framework import serializers
    
    # 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
    class StudentSerializer(serializers.Serializer):
        """商品信息序列化器"""
    
        name = serializers.CharField()
        price = serializers.IntegerField()
        
        
    	一,序列化时:没啥可说的,就是把模型对象转换成字典
        
        二,反序列化时:
            1,先判断接受的数据是否符合参数规则
            2,符合规则的数据放入到validate_data中
            3,修改表模型对象属性,手动操作,重写updata或create方法,因为Serializer没有提供这两个方法
            def update (self,instance,validate_data):
            	instance.name=validate_data.get('name')
                instance.price=validate_data.get('price')
                instance.save() #表模型对象的save方法
                
            def create(self,instance,validate_data):
                models.Book.object.create(**validate_data)
                
            4,调用序列化器的.save()方法内部会调用update或save方法,数据就存入表中了
            
         三,反序列化的额外方法:
            1)validators法:该方法将和校验函数配置在参数里
                name = serializers.CharField(validators=[check_func])
                
                def check_func(data):
                    业务逻辑代码
                    
            2)局部校验和全局校验两种方法:
                局部校验钩子函数:函数命名规则--validate_字段名
                    def validate_price(self,data):
                    	业务逻辑代码
                
                全局校验钩子函数:函数命名规则--validate
                    def validate(self,validated_data):
                        业务逻辑代码
            如果校验不通过就要抛出异常:
                raise ValidationError('错误提示')
                
            校验通过就返回数据
            
          四,返回和接收的数据的字段不一样怎么办?参数中加入下面两个参数
        	name = serializers.CharField(read_only = True)
        	read_only = True #只读字段
            write_only = True #只写字段
            
          五,如何自定义返回查表结果?Serializer高级用法
        	# source的使用
            1 可以改字段名字  xxx=serializers.CharField(source='title') #title是表中有的字段
            2 可以跨表publish=serializers.CharField(source='publish.email')#跨表的前提是publish是			外键字段,而且email在publish表中
            3 可以执行方法pub_date=serializers.CharField(source='test') #test是Book表模型中的方法
    
    
        	# SerializerMethodField()更强的自定义输出结果
            1 它需要有个配套方法,方法名叫get_字段名,返回值就是要显示数据
            authors=serializers.SerializerMethodField() 
            
            def get_authors(self,instance):
                # book对象
                authors=instance.authors.all()  # 取出所有作者
                ll=[] #编辑自定义的查询结果
                for author in authors:
                    ll.append({'name':author.name,'age':author.age})
                return ll
        	
        
                
               
    

    2.2 全自动序列化器ModelSerializer

    提供了create()和update()方法,可以直接调用了,但是不会自动执行
    (如果继承了UpdateModelMixin,CreateModelMixin,这两个类会去验证数据是否合法并调用create()和update()方法)

    使用:

    1.我们创建一个BookInfoSerializer
    
    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = (name,)
    model指明参照哪个模型类
    fields指明为模型类的哪些字段生成
    
    
    2.指定字段
        #fields详解:
            fields内可以填入有1(model字段),2(model中定义的方法),3(SerializerMethodField()字段),4(子序列化字段)
            1)表模型对应的字段:直接序列化字段的内容,若是外键字段返回一个对象的打印结果,需要在表模型中重写				__str__方法
            2)model中定义的方法:序列化方法的结果,一般用来定制外键字段输出的信息,
            3)SerializerMethodField()字段 和2.1的使用方法一样,需要额外添加字段	
            4)子序列法 直接引用其他序列化器的结果,也需要额外添加字段
            class BookInfoSerializer(serializers.ModelSerializer):
                """图书数据序列化器"""
                authors=serializers.SerializerMethodField()
                authors=AuthorSerializer() #子序列化需要添加的字段
                class Meta:
                    model = BookInfo
                    fields = (name,authors,)	
            
    注意:不是实实在在存在表中的字段都需要设置为只读,否则写入时报错!
        read_only_fields = ('id',)
            
    3.添加额外参数 extra_kwargs
    	我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
    
        class BookInfoSerializer(serializers.ModelSerializer):
            """图书数据序列化器"""
            class Meta:
                model = BookInfo
                fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
                extra_kwargs = {
                    'bread': {'min_value': 0, 'required': True},
                    'bcomment': {'min_value': 0, 'required': True},
                }
    
    

    2.3 序列化器的使用

    基本用法

    基于APIView视图类的使用

    1) 先查询出一个对象

    from students.models import Student
    
    student = Student.objects.get(id=3)
    

    2) 构造序列化器对象

    from .serializers import StudentSerializer
    
    serializer = StudentSerializer(instance=student)
    

    3)获取序列化数据

    通过data属性可以获取序列化后的数据,是一个字典

    serializer.data
    # {'id': 4, 'name': '小张', 'age': 18, 'sex': True, 'description': '猴赛雷'}
    

    说明

    1)用于序列化时,只传一个instance参数,默认第一个参数

    2)用于反序列化时,只传入data参数

    1. 同时传入 instance,data字段进行修改操作

    4)如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

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

    serializer = AccountSerializer(account, context={'request': request})
    
    基于GenericAPiView配合Mixin类的使用
    见4.3
    

    高级用法

    1.重写serializer的validate方法,通过context参数将数据传入序列化类中,实现复杂的业务逻辑在序列化类里判断

    2.重写create或update方法实现一次性操作多张表,或其他业务需求

  • 相关阅读:
    vite启用host代理,自动无限刷新问题
    机器人语音交互
    让or使用索引
    leetcode 77. Combinations 组合(中等)
    leetcode 257. Binary Tree Paths 二叉树的所有路径(简单)
    leetcode 934. Shortest Bridge 最短的桥(中等)
    为什么 SQL 语句使用了索引,但却还是慢查询?
    leetcode 47. Permutations II 全排列 II(中等)
    leetcode 79. Word Search 单词搜索
    leetcode 126. Word Ladder II 单词接龙 II(困难)
  • 原文地址:https://www.cnblogs.com/Franciszw/p/13552259.html
Copyright © 2020-2023  润新知