三、drf序列化器-Serializer

'''
作用:

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

ps:模型可以看作是models表


序列化器的使用与forms组件的使用非常相似
'''

一、定义序列化器

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

# 在app下创建书写序列化器的py文件
import rest_framework.serializers

class 序列化器类名(serializers.Serializer):
    属性名 = serializers.CharField()
    ....
    # 序列化器中的属性名,需要和模型表中的属性名一致

1、常用字段类型

字段字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField() (null、True、False)
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=)

2、选项参数

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

3、通用参数

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

4、source参数

address = serializers.CharField()
'''
详细:
    1. 因为序列化时,传递的是表对象 book_obj = models.xxx.objects.filter(xxx).first()

    2. 此刻就相当于 book_obj.address

    3. 如果表内不存在address字段,则会报错

source参数的作用就是指定 book_obj.source参数值,可以如ORM一样,操作外键、字段等

PS:
    1. 如果外键关联表内定义了 __str__方法,并返回了值,那么address就使用该返回值
    2. source不仅可以填写模型表中的属性名,还可以填写方法名,会执行该方法,获取方法的返回结果!
'''
# 外键使用(一对多,正向)
address = serializers.CharField(source='FK')    ---> first()    记录对象
# 外键使用(多对多,正向)
address = serializers.CharField(source='FK')    ---> app01.表名.None    表对象

5、SerializerMethodField()字段

'''
在source参数中,已经介绍了如何实现序列化器与模型表属性不一致,和其对应原理

对应的问题就来了:
    1. 如果是多对多/一对多,我如何在一个序列化属性中包含所有需要的信息,而不是单纯的一个表对象、一个值
'''
address = serializers.SerializerMethodField()
'''
SerializerMethodField()还必须要定义一个配套方法,方法名必须叫get_字段名,返回值就是要显示的东西
'''
def get_address(self,instance):
        '''
        因为序列化时,传递的是表对象 book_obj = models.xxx.objects.filter(xxx).first()
        instance    就相当于book_obj
        FK            就是book_obj中的外键
        '''
        address=instance.FK.all()  
        
        ll=[]
        for i in address:
            ll.append({
                'name': i.name,
                'age':i.age
            })
        return ll

 

二、模型表序列化器

使用模型表序列化器,无需重写update、create方法

from rest_framework.serializers import ModelSerializer
from app01 import models

class 序列化器类名(ModelSerializer):
    class Meta:
        model = models.模型表名        # 代表指定的模型表
        fields = '__all__'            # 代表模型表内所有属性
        # fields = ('模型表属性名',...)    指定属性名,也可以使用列表括起

        exclude=('模型表属性名',...)        
        # 代表除了指定的属性,排除。与fields只能存在一个
        
        read_only_fields=('模型表属性名',...)    
        # 代表该属性设置为只用于序列化输出
        # write_only_fields=()    弃用
        
        extra_kwargs = {
            '模型表属性名': {
                '参数1': 参数值,
                ...
            }
            ...
        }
        # 为指定属性添加serializers参数

三、使用序列化器

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

说明:
    1)用于序列化时,将模型类对象传入instance参数
    2)用于反序列化时,将要被反序列化的数据传入data参数
     3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如
        Zzw = ZzwSerializer(account, context={'request': request})
    4)如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

PS: 
    模型表数据即:models.xxx.objects.filter('xxx').first()
    通过context参数附加的数据,可以通过Zzw对象的context属性获取。
    
1. 序列化器会自动帮我们把模型数据转换成字典.
2. drf提供的视图会帮我们把发出的字典转换成json,或者把客户端发送过来的数据转换字典


序列化器的使用分两个阶段:
    在客户端请求时,使用序列化器可以完成对数据的反序列化。
    在服务器响应时,使用序列化器可以完成对数据的序列化。
'''

变量名 = 序列化器类名(instance=None, data=empty, **kwargs)

'''
序列化使用:
    instance=放入需要序列化的数据 变量名

反序列化使用:
    data=接收前端发来的数据,request.data
    
数据修改:
    需要使用instance、data参数同时指定,用于指定需要修改的数据
'''

1、many=True

'''
序列化多条,需要使用many=True参数,设置了此参数和没设置此参数,返回的对象截然不同,造成此结果的原因在于父类方法中的__new__()方法

many=True
    <class 'rest_framework.serializers.ListSerializer'>
many=False
    <class 'app01.ser.BookModelSerializer'>

ListSerializer对象,相当于就是一个列表,内部是多个BookModelSerializer对象
'''
def __new__(cls, *args, **kwargs):
    if kwargs.pop('many', False):
        return cls.many_init(*args, **kwargs)
    # 没有传many=True,走下面,正常的对象实例化
    return super().__new__(cls, *args, **kwargs)

四、序列化器的常用方法

1、update(更新数据)

def update(self, instance, validated_data):
        '''
        instance:模型表对象
        validated_data:经由序列化器校验通过后的数据对象(request.data)
        '''
        instance.name=validated_data.get('name')
        instance.price=validated_data.get('price')
        instance.author=validated_data.get('author')
        instance.publish=validated_data.get('publish')
        instance.save()  
        # ORM提供的save方法,用于提交数据库修改操作,与序列化器的save放啊并不是同一个
        return instance
    
'''
数据修改:
    需要使用instance、data参数同时指定,用于指定需要修改的数据
'''

2、create(增加数据)

def create(self, validated_data):
    '''
    validated_data:经由序列化器校验通过后的数据对象(request.data)
    '''
    instance =  models.xxx.objects.create(**validated_data)
    return instance

3、删除/查看

'''
删除和查看没有序列化器方法
    查看:对于查看,我们只需要返回序列化后的数据即可
    删除:对于删除,我们只需要在delete方法内直接删除指定pk的数据即可
'''
# 查询所有
class BooksView(APIView):
    def get(self,request):
        # 定义规范字典
        response_msg = {'status': 100, 'msg': '成功'}
        
        # 获取表中所有数据
        books=models.Book.objects.all()
        
        # 序列化多条,如果序列化一条,不需要写
        book_ser=BookSerializer(books,many=True)  
        
        # 将表中数据放入到规范字典中
        response_msg['data']=book_ser.data
        
        # 返回给前端
        return Response(response_msg)

# 删除
    def put(self, request, pk):
        # 定义规范字典
        
        response_msg = {'status': 100, 'msg': '删除成功'}
        
        models.xxx.objects.filter(id=pk).delete()
        
        # 返回给前端
        return Response(response_msg)

五、增加校验规则(钩子)

1、validate_字段名(局部钩子)

def validate_price(self, data):
    # data代表当前单个字段的值
    if data == 'xxx':
        raise ValidationError('....')
    else:
        return data

2、validate(全局钩子)

def validate(self, attrs): 
    # attrs代表所有字段的值(request.data)
    a1 = attrs.get('xxx')
    a2 = attrs.get('xxx')
    ...
    
    if 条件判断:    # (例如:a1 == a2)
        raise ValidationError('....')
    else:
        return data

3、使用validators参数

'''
serializers字段使用validators参数,可以绑定函数,将反序列化时,该字段的值传入到该函数中,进行进一步校验。
    validators = [函数名]

直接在序列化器当前文件内,定义一个方法,对绑定字段的反序列化值进行处理
'''
# 例如:
author=serializers.CharField(validators=[check_author])

def check_author(data):
    if data.startswith('sb'):
        raise ValidationError('作者名字不能以sb开头')
    else:
        return data

六、序列化器对象方法/属性

1、data

data_serializers = ZzwSerializers(instance=模型表数据变量名)

data_serializers.data
'''
1. 返回 模型表数据变量名中的数据,一个字典,k为模型表属性名,v为模型表该属性对应存储值

例如:
    {'id': 4, 'name': '小张', 'age': 18, 'sex': True, 'description': '猴赛雷'}
'''

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

ceshi = ZzwSerializer(instance=student_list,many=True)
print( ceshi.data ) # 序列化器转换后的数据
'''
[
OrderedDict([('id', 1), ('name', 'xiaoming'), ('age', 20), ('sex', True), ('description', '测试')]), 
OrderedDict([('id', 2), ('name', 'xiaohui'), ('age', 22), ('sex', True), ('description', '后面来的测试')]), 
OrderedDict([('id', 4), ('name', '小张'), ('age', 18), ('sex', True), ('description', '猴赛雷')])
]
'''

2、errors

data_serializers = ZzwSerializers(instance=模型表数据变量名, data=request.data)

data_serializers.is_valid()

3、context

data_serializers = ZzwSerializers(instance=模型表数据变量名, data=empty, context={'request': '123'})

data_serializers.context
# {'request': '123'}

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

4、save()

data_serializers = ZzwSerializers(instance=模型表数据变量名)

data_serializers.save()
# 触发调用序列化器中的update方法,进行数据更新操作,如果不存在update方法,则会报错

5、is_valid()

data_serializers = ZzwSerializers(instance=模型表数据变量名, data=request.data)

data_serializers.is_valid(raise_exception=True)

'''
1. is_valid()方法用于判断前端传递的数据是否符合序列化器规定的数据规则,返回bool值,符合True
2. is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
'''

七、封装返回code码

class mycode()
    def __init__(self):
        self.code = 100
        self.msg = '成功'
    
    @property
    def code_dict(self):
        return self_dict__

 

posted @ 2021-07-04 19:31  zzwYYYYYY  阅读(304)  评论(0)    收藏  举报