Django DRF - 反序列化的验证

本文介绍了DjangoRESTFramework(DRF)中序列化器在反序列化时的数据验证过程。通过`is_valid()`方法进行验证,验证失败则返回错误信息。文章详细展示了基本认证和自定义验证方法,包括字段类型、字段选项、`validate_fieldname`和`validate`方法。并提供了示例代码来说明如何处理字段验证和异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  • 使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
  • 在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
  • 验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
  • 验证成功,可以通过序列化器对象的validated_data属性获取数据。
  • 在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

一. 基本认证

定义BookInfoSerializer

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID')
    name = serializers.CharField(label='名称')
    pub_date = serializers.DateField(label='发布日期')
    readcount = serializers.IntegerField(label='阅读量')
    commentcount = serializers.IntegerField(label='评论量')

通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证
基本认证类型-字段

>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'name':'Python',
...     'pub_date':'2020-1-1',
...     'readcount':100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'id':100,
...     'name':'Python',
...     'pub_date':'2020-1-1',
...     'readcount':100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> serializer.is_valid()
True

在这里插入图片描述

is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。

>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'id':100,
...     'name':'Python高级',
...     'pub_date':'2020', 
...     'readcount':100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> serializer.is_valid()
False
>>> 
>>> serializer.errors
{'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY-MM-DD.', code='invalid')]}

以上提示明显看出是日期格式不对

二. 自定义添加认证

如果觉得这些还不够,可以使用以下几种方法验证:
并且认证的时候认证的顺序是

字段类型->字段选项->validate_fieldname-> validate

1) 字段类型

常用字段类型:

字段	字段构造方式
BooleanField	BooleanField()
NullBooleanField	NullBooleanField()
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) 字段选项

通用参数

参数名称	说明
read_only	表明该字段仅用于序列化输出,默认False
write_only	表明该字段仅用于反序列化输入,默认False
required	表明该字段在反序列化时必须输入,默认True
default	反序列化时使用的默认值
label	用于HTML展示API页面时,显示的字段名称
allow_null	表明该字段是否允许传入None,默认是False

选项参数

参数名称	作用
max_length	最大长度
min_lenght	最小长度
allow_blank	是否允许为空
max_value	最大值
min_value	最小值

在序列化器中,定义的字段选项默认是required。

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID')
    name = serializers.CharField(label='名称')
    pub_date = serializers.DateField(label='发布日期')
    readcount = serializers.IntegerField(label='阅读量')
    commentcount = serializers.IntegerField(label='评论量')

如果我们传递数据缺失一个id会怎么样呢?

>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'name':'Python高级',
...     'pub_date':'2020-01-01',
...     'readcount':100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> serializer.is_valid(raise_exception=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ubuntu/.virtualenvs/py3_django_2_2_5/lib/python3.6/site-packages/rest_framework/serializers.py", line 242, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'id': [ErrorDetail(string='This field is required.', code='required')]}
>>>

在这里插入图片描述
read_only
像id这样的主键值,一般我们都是让数据库自动生成,所以一般不会传入。则需要设置为 read_only

id = serializers.IntegerField(label='ID',read_only=True)
  • 表明该字段仅用于序列化输出,反序列化的时候忽略

write_only
只写入。我们在进行反序列化的时候,必须要求传入该字段。在进行序列化操作的时候不会获取到该字段的值。

password = serializers.IntegerField(label='密码',read_only=True)
  • 表明该字段仅用于反序列化输入,序列化的时候忽略

3) validate_fieldname(单个字段)

<field_name>字段进行验证,如

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名称', max_length=20)
    pub_date = serializers.DateField(label='发布日期', required=False)
    readcount = serializers.IntegerField(label='阅读量', required=False)
    commentcount = serializers.IntegerField(label='评论量', required=False)

    def validate_readcount(self,value):
        if value < 0:
            raise serializers.ValidationError('阅读数量不能为负数')
        return value

测试

>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'name':'Python高级',
...     'pub_date':'2020-01-01',
...     'readcount':-100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> serializer.is_valid(raise_exception=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ubuntu/.virtualenvs/py3_django_2_2_5/lib/python3.6/site-packages/rest_framework/serializers.py", line 242, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'readcount': \[ErrorDetail(string='阅读数量不能为负数', code='invalid')\]}

duoge

4) validate(多个字段)

在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名称', max_length=20)
    pub_date = serializers.DateField(label='发布日期', required=False)
    readcount = serializers.IntegerField(label='阅读量', required=False)
    commentcount = serializers.IntegerField(label='评论量', required=False)

    def validate(self, attrs):
        readcount = attrs['readcount']
        commentcount = attrs['commentcount']
        if commentcount > readcount:
            raise serializers.ValidationError('评论量不能大于阅读量')
        return attrs

测试

>>> from book.serializers import BookInfoSerializer
>>> 
>>> data = {
...     'name':'Python高级',
...     'pub_date':'2020-01-01',
...     'readcount':100,
...     'commentcount':200
... }
>>> 
>>> serializer = BookInfoSerializer(data=data)
>>> 
>>> serializer.is_valid(raise_exception=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/ubuntu/.virtualenvs/py3_django_2_2_5/lib/python3.6/site-packages/rest_framework/serializers.py", line 242, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'non_field_errors': [ErrorDetail(string='评论量不能大于阅读量', code='invalid')]}
>>>

在这里插入图片描述
ok, 以上就是django DRF 框架反序列化的基本认证功能介绍,希望对你有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天下·第二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值