三、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__

浙公网安备 33010602011771号