drf-02-序列化器、数据验证(is_valid())、保存数据(create,save。。。⼀、序列化器-Serializer
序列化,序列化器会把模型对象转换成字典,经过respon以后变成json字符串
反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
反序列化,完成数据校验功能
1.定义序列化器
Django REST framework中的Serializer使⽤类来定义,须继承⾃rest_framework.rializers.Serializer
先创建⼀个新的⼦应⽤rs
python manage.py startapp rs
已有了⼀个数据库模型类students/Student
from django.db import models
# Create your models here.
class Student(models.Model):
# 模型字段
name = models.CharField(max_length=100,verbo_name="姓名",help_text="提⽰⽂本:账号不能为空!")
x = models.BooleanField(default=True,verbo_name="性别")
age = models.IntegerField(verbo_name="年龄")
class_null = models.CharField(max_length=5,verbo_name="班级编号")
description = models.TextField(verbo_name="个性签名")
class Meta:
db_table="tb_student"
verbo_name ="学⽣"
verbo_name_plural = verbo_name
想为这个模型类提供⼀个序列化器,可以定义如下:
from rest_framework import rializers
# 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
# 其中,ModelSerializer是Serializer的⼦类,ModelSerializer在Serializer的基础上进⾏了代码简化
class StudentSerializer(rializers.Serializer):
"""学⽣信息序列化器"""
# 需要进⾏数据转换的字段
id= rializers.IntegerField()
name = rializers.CharField()
age = rializers.IntegerField()
x = rializers.BooleanField()
description = rializers.CharField()
注意:rializer不是只能为数据库模型类定义,也可以为⾮数据库模型类的数据定义。 rializer是独⽴于数据库之外的存在。
常⽤字段类型:
字段字段构造⽅式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=Fal, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=Fal)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=Fal)
SlugField SlugField(max length=50, min_length=None, allow_blank=Fal) 正则字段,验证正则模式
[a-zA-Z0-9-]+
SlugField SlugField(max length=50, min_length=None, allow_blank=Fal) 正则字段,验证正则模式 [a-zA-Z0-9-]+ URLField URLField(max_length=200, min_length=None, allow_blank=Fal)
UUIDField UUIDField(format=‘hex_verbo’) format: 1) 'hex_verbo’如"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=Fal, **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_ttings.DATETIME_FORMAT, input_formats=None) DateField DateField(format=api_ttings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_ttings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的⽤法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=Fal, u_url=UPLOADED_FILES_USE_URL) ImageField ImageField(max_length=None, allow_empty_file=Fal, u_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表明该字段仅⽤于序列化输出,默认Fal
write_only表明该字段仅⽤于反序列化输⼊,默认Fal
required表明该字段在反序列化时必须输⼊,默认True
default反序列化时使⽤的默认值
allow_null表明该字段是否允许传⼊None,默认Fal
validators该字段使⽤的验证器
error_messages包含错误编号与错误信息的字典
error_messages包含错误编号与错误信息的字典
参数名称说明
label⽤于HTML展⽰API页⾯时,显⽰的字段名称
help_text⽤于HTML展⽰API页⾯时,显⽰的字段帮助提⽰信息
2.创建Serializer对象
Serializer的构造⽅法为:
Serializer(instance=None, data=empty, **kwarg)
说明:
1)序列化时,将模型类对象传⼊instance参数
2)反序列化时,将要被反序列化的数据传⼊data参数
3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如
rializer = AccountSerializer(account, context={'request': request})
通过context参数附加的数据,可以通过Serializer对象的context属性获取。
⼆、序列化器的使⽤
序列化器的使⽤分两个阶段:
在客户端请求时,使⽤序列化器可以完成对数据的反序列化。
在服务器响应时,使⽤序列化器可以完成对数据的序列化。
1.反序列化
1)数据验证(is_valid())
使⽤序列化器进⾏反序列化时,需要对数据进⾏验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调⽤is_valid() ⽅法进⾏验证,验证成功返回True,否则返回Fal。
验证失败,可以通过序列化器对象的errors 属性获取错误信息,返回字典,包含了字段和字段的错误。如果是⾮字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的validated_data属性获取数据。
在定义序列化器时,指明每个字段的序列化类型和选项参数,本⾝就是⼀种验证⾏为。
定义序列化器,代码:
from rest_framework import rializers
class StudentSerializer(rializers.Serializer):
# 需要转换的字段声明
# ⼩括号⾥⾯声明主要提供给反序列化使⽤的
name = rializers.CharField(required=True, max_length=20)
age = rializers.IntegerField(max_value=150, min_value=0,required=True)
x = rializers.BooleanField(default=True)
description = rializers.CharField(required=Fal,allow_null=True, allow_blank=True)#required=Fal,字段都可以不传递给后端,allow_null=True,允许提交过来的数据为空值(null--None),allow_blank=True 允许提交过来的数据为空字符串
通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进⽽进⾏验证
# Create your views here.
from django.http import JsonRespon
from django.views import View
from.rializers import StudentSerializer
dels import Student
class StudentView(View):
def post(lf,request):
"""添加⼀个学⽣"""
# 接受参数
post_data = request.POST
data ={
"name":('name'),
"age":('age'),
"x":('x'),
"description":('description'),
}
# 调⽤序列化器进⾏反序列化验证和转换
rializer = StudentSerializer(data=data)
# 当验证失败时,可以直接通过声明 rai_exception=True 让django直接跑出异常,那么验证出错之后,直接就再这⾥报错,程序中断了就
result = rializer.is_valid(rai_exception=True)
print("验证结果:%s"% result )
# 获取通过验证后的数据
print( rializer.validated_data )# form -- clean_data
# 保存数据
student = ate(
name=rializer.("name"),
age=rializer.("age"),
x=rializer.("x")
)
print(student)
# 返回响应结果给客户端
# alt + enter,可以实现快速导包
return JsonRespon({"message":"ok"})
is_valid()⽅法还可以在验证失败时抛出异常rializers.ValidationError,可以通过传递rai_exception
=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
rai_exception参数
等于True会主动抛异常
rializer.is_valid(rai_exception=True)
全局钩⼦(validate)和局部钩⼦(validate_ )的使⽤
class StudentSerizlizer(rializers.Serializer):
# <QueryDict: {'name': ['c777'], 'age': ['6'], 'description': ['123'], 'class_null': ['1']}>
name = rializers.CharField(max_length=4,validators=[check666,])
age = rializers.IntegerField(max_value=18)
class_null = rializers.CharField()
# description = rializers.CharField(required=Fal,allow_null=True)
# required=Fal,allow_null=True允许字段为空,也就是不⽤传递过来这个data
description = rializers.CharField(allow_blank=True)
#allow_blank=True 允许只为空字符串
# 局部钩⼦:针对单个属性对应的数据进⾏校验
def validate_name(lf,val):
# print('xxxxx>>>',val) #xxxxx>>> ccbb
if'777'in val:
rai rializers.ValidationError('不能有777')
return val #如果没有错误,需要return这个属性数据
# 全局钩⼦:主要是针对多个属性数据进⾏校验
def validate(lf,data):
print(data)#OrderedDict([('name', 'c778'), ('age', 6), ('class_null', '1'), ('description', '123')])
age = ('age')
class_null = ('age')
if age == class_null:
rai rializers.ValidationError('age和class——null不能相等')
return data #如果没有错误,全局钩⼦要return所有数据
视图部分
def post(lf,request):
#
print(request.POST)
data ={
'name':('name'),
'age':('age'),
'class_null':('class_null'),
'description':('description'),
}
r = StudentSerizlizer(data=data)
if r.is_valid():
print(request.body)
ret = models.ate(
**r.validated_data
)
rializer = StudentSerizlizer(instance=ret)
print(rializer.data)#得到的是教研成功之后的所有正确数据
return JsonRespon(rializer.data,safe=Fal,json_dumps_params={'ensure_ascii':Fal}) # return JsonRespon({'xx':'xx'})
el:
return JsonRespon({'error':'有字段错误'})
执⾏顺序如下