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方法实现一次性操作多张表,或其他业务需求

posted @ 2020-08-24 10:04  Franciszw  阅读(181)  评论(0编辑  收藏  举报