反序列化使用
验证
利用之前的模型类进行验证,
>>> from booktest.models import BookInfo,HeroInfo
>>> from booktest.serializers import BookInfoSerializer
>>> from booktest.serializers import HeroInfoSerializer
>>> data = {'bpub_date':123}
>>> s = BookInfoSerializer(data= data)
>>> s.is_valid()
False
>>> s.errors
{'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')]}
>>> s.validated_data
{}
构造序列化器对象,并将要反序列化的数据传给data构造成参数,进行验证
使用序列化器进行反序列化时,需要对数据进行验证,才能获取验证成功的数据或者保存的模型类的对象
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成返回True,失败返回False
验证失败之后,通过序列化器对象的errors属性获取错误信息,返回字典,包含错误的字段和字段的错误信息.如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过validated_data属性获取数据
is_valid()在验证失败时抛出异常serializers.ValidationError,通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
serializer.is_valid(raise_exception=True)
补充验证行为的三种方法:
Validate_<filed_name> 对filed_name字段进行验证
class BookInfoSerializers(serializers.Serializer):
"""图书数据管理序列化器"""
......
def validate_btitle(self,value):
"""对传入标题进行验证"""
if 'python' not in value.lower(): #不区分大小写
raise serializers.ValidationError('书籍名称中不包含python')
return value
验证结果:
>>> from booktest.serializers import BookInfoSerializer
>>> data = {'btitle':'python'}
>>> s= BookInfoSerializer(data = data)
>>> s.is_valid
<bound method BaseSerializer.is_valid of BookInfoSerializer(data={'btitle': 'python'}):
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期', required=False)
bread = IntegerField(label='阅读量', required=False)
bcomment = IntegerField(label='评论量', required=False)
image = ImageField(label='图片', required=False)>
>>> s.is_valid()
True
>>> s.errors
{}
错误结果:
>>> from booktest.serializers import BookInfoSerializer,HeroInfoSerializer
>>> data= {'btitle':'Django'}
>>> s = BookInfoSerializer(data=data)
>>> s.is_valid()
False
>>> s.errors
{'btitle': [ErrorDetail(string='书籍名称中不包含python', code='invalid')]}
validators
def btitle_python(self,value):
"""对传入标题进行验证"""
if 'python' not in value.lower(): #不区分大小写
raise serializers.ValidationError('书籍名称中不包含python')
return value
class BookInfoSerializer(serializers.Serializer):
"""图书数据管理序列化器"""
id = serializers.IntegerField(label='ID',read_only=True)
btitle = serializers.CharField(label='名称',max_length=20,validators=[btitle_python]) #添加validators选项参数进行书名验证
验证结果:
正确的验证:
>>> from booktest.serializers import BookInfoSerializer
>>> data={'btitle':'python3.6'}
>>> s = BookInfoSerializer(data=data)
>>> s.is_valid()
True
>>> s.errors
{}
错误情况下:
>>> data={'btitle':'django'}
>>> s= BookInfoSerializer(data=data)
>>> s.is_valid()
False
>>> s.errors
{'btitle': [ErrorDetail(string='书籍名称中不包含python', code='invalid')]}
validate
对多个字段进行验证时,可以用validate方法
def validate(self, attrs):
"""
validate方法验证多个字段
attrs是内置属性
:return attrs 同value相同
"""
bread = attrs['bread']
bcomment = attrs['bcomment']
if bread < bcomment:
raise serializers.ValidationError('阅读量小于评论量')
return attrs
验证结果:
>>> from booktest.serializers import BookInfoSerializer
>>> data = {'bread':10,'bcomment':20} # 不传btitle的值 会报错
>>> s = BookInfoSerializer(data=data)
>>> s.is_valid()
False
>>> s.errors
{'btitle': [ErrorDetail(string='This field is required.', code='required')]}
传入字段btitle的值
>>> data = {'btitle':'python2.5','bread':13,'bcomment':23}
>>> s = BookInfoSerializer(data=data)
>>> s.is_valid()
False
>>> s.errors
{'non_field_errors': [ErrorDetail(string='阅读量小于评论量', code='invalid')]}