drf验证
is_valid
反序列化时,始终需要验证is_valid()
,否则将抛出异常。如果发生任何验证错误(serializers.ValidationError
),.errors
属性可以获取错误字典。字典里的每一个键都是字段名称,值是与该字段对应的任何错误消息的字符串列表。non_field_errors
键可能存在,它将列出任何一般验证错误信息。non_field_errors的名称可以通过REST framework设置中的NON_FIELD_ERRORS_KEY
来自定义。 当对对象列表进行序列化时,返回的错误是每个反序列化项的字典列表。
serializer = CommentSerializer(data={})
serializer.is_valid()
# False
serializer.errors
输出结果,
{
"name": [
"该字段不能为空。"
],
"price": [
"请填写合法的数字。"
],
"description": [
"该字段不能为空。"
],
"release_date": [
"日期格式错误。请从这些格式中选择:YYYY-MM-DD。"
]
}
并且is_valid
有一个参数raise_exception
默认为False
。如果使用默认值,验证失败继续保存将直接抛出异常。如果为True
异常将被drf
默认异常'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
所捕获处理后返回给前端。
def exception_handler(exc, context):
"""
Returns the response that should be used for any given exception.
By default we handle the REST framework `APIException`, and also
Django's built-in `Http404` and `PermissionDenied` exceptions.
Any unhandled exceptions may return `None`, which will cause a 500 error
to be raised.
"""
if isinstance(exc, Http404):
exc = exceptions.NotFound()
elif isinstance(exc, PermissionDenied):
exc = exceptions.PermissionDenied()
if isinstance(exc, exceptions.APIException):
headers = {}
if getattr(exc, 'auth_header', None):
headers['WWW-Authenticate'] = exc.auth_header
if getattr(exc, 'wait', None):
headers['Retry-After'] = '%d' % exc.wait
if isinstance(exc.detail, (list, dict)):
data = exc.detail
else:
data = {'detail': exc.detail}
set_rollback()
return Response(data, status=exc.status_code, headers=headers)
return None
基础序列化器
from rest_framework import serializers
class BaseSerializer(serializers.Serializer):
email = serializers.EmailField(required=False)
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
字段级别认证
通过Serializer
中添加validate_<field_name>
方法来指定自定义字段级别的验证。验证失败抛出serializers.ValidationError
后被exception_handler
捕获。
class CommentSerializer(BaseSerializer):
@staticmethod
def validate_content(value):
"""
Check that the blog post is about Django.
"""
if len(value) < 20:
raise serializers.ValidationError("你太短了")
return value
# 返回结果
# {
# "content": [
# "你太短了"
# ]
# }
对象级别的验证
要执行需要访问多个字段的任何其他验证,请添加一个validate
方法到Serializer
子类中。这个方法采用字段值字典的单个参数,如果需要应该抛出一个 ValidationError
异常,或者只是返回经过验证的值。
class CommentSerializer(BaseSerializer):
def validate(self, attrs):
if not attrs['email']:
raise serializers.ValidationError("邮箱不能为空")
return attrs
验证器
序列化器上的各个字段都可以包含验证器,通过在字段实例上声明
def verify_email(value):
if not value:
raise serializers.ValidationError("邮箱不能为空")
class BaseSerializer(serializers.Serializer):
email = serializers.EmailField(required=False, validators=[verify_email])
content = serializers.CharField(max_length=200)
created = serializers.DateTimeField()
额外的上下文参数
在序列化器中若何使用rest_framework 中 request
。最原始的方式是手动通过Serializer(xx, context={'request': request})
传递。或者高级API提供这个能力GenericAPIView
及以上,get_serializer_context
更加方便做一些操作。