【Django Rest framework】Validators篇翻译及应用举例

内容介绍

在你使用 REST 框架进行验证处理时,你可能仅仅依赖于默认依赖的字段验证或者在 serializer 上使用显式验证的方法,但如果将验证逻辑代码放入可复用的组件中可达到复用代码降低冗余的效果,而这个功能就可以通过验证类或者验证函数来实现。

Validators举例

models.py

class CustomerReportRecord(models.Model):
    time_raised = models.DateTimeField(default=timezone.now, editable=False)
    reference = models.CharField(unique=True, max_length=20)
    description = models.TextField()

serializers.py

class CustomerReportSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomerReportRecord

主要功能类型

UniqueValidator

该验证类, 用于 unique=True 的模型字段约束。
参数
– queryset:必须参数, 用于执行约束的查询集
– message:验证失败返回的错误信息
– lookup:用于查找具有正在验证的值的现有实例的查找。默认为 “exact”

from rest_framework.validators import UniqueValidator

class ...:
	...
    slug = SlugField(
        max_length=100,
        validators=[UniqueValidator(queryset=BlogPost.objects.all())]
    )

UniqueTogetherValidator

该验证类用于多字段下的组合约束。
参数
– queryset:必须参数, 用于执行约束的查询集
– message:验证失败返回的错误信息
– fields:必须参数, 用于联合唯一约束的字段列表或元组

from rest_framework.validators import UniqueTogetherValidator

class ExampleSerializer(serializers.Serializer):
    ...
    class Meta:
        validators = [
            UniqueTogetherValidator(
                queryset=ToDoItem.objects.all(),
                fields=['list', 'position']
            )
        ]

UniqueForDateValidator、UniqueForMonthValidator、UniqueForYearValidator

该三个验证类用于时间模型字段的限制约束。
参数
– queryset:必须参数, 用于执行约束的查询集
– message:验证失败返回的错误信息
– field:必须参数, 用于约束的时间字段名称
– date_field:必须参数, 用于确定唯一性约束的日期范围

from rest_framework.validators import UniqueForYearValidator

class ExampleSerializer(serializers.Serializer):
    ...
    class Meta:
        validators = [
            UniqueForYearValidator(
                queryset=BlogPostItem.objects.all(),
                field='slug',
                date_field='published'
            )
        ]
  1. 日期字段可写的方式
publishTime = serializers.DateTimeField(required=True)
  1. 日期字段可读、不可编辑
publishTime = serializers.DateTimeField(read_only=True, default=timezone.now)
  1. 日期字段隐藏
publishTime = serializers.HiddenField(default=timezone.now)

默认值高级用法

  1. CurrentUserDefault
    显示当前model默认类
owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)
  1. CreateOnlyDefault
    在创建时用于默认值, 更新操作时将忽略该字段
created_at = serializers.DateTimeField(
    default=serializers.CreateOnlyDefault(timezone.now)
)

复杂的验证

class BillingRecordSerializer(serializers.ModelSerializer):
    def validate(self, attrs):
        # 应用自定义验证方式.

    class Meta:
        fields = ['client', 'date', 'amount']
        extra_kwargs = {
    
    'client': {
    
    'required': False}}
        validators = []  # 删除默认的 "unique together" 约束

自定义验证

验证器是可以引发 serializers.ValidationError 异常的任何可调用对象

def even_number(value):
    if value % 2 != 0:
        raise serializers.ValidationError('This field must be an even number.')

定义的 Serializer 中, 针对某一个字段进行特殊的验证,在 Serializer 中定义添加 .validate_<field_name> 方法实现

class BillingRecordSerializer(serializers.ModelSerializer):
    def validate_title(self, attrs):
        # 在此处或视图中应用自定义验证.

更高复用性类的方式重写 call 方法

class MultipleOf:
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if value % self.base != 0:
            message = 'This field must be a multiple of %d.' % self.base
            raise serializers.ValidationError(message)

验证器传递与之一起使用的序列化器字段作为附加上下文,通过在设置 requires_context = True 属性来完成此操作,将使用 serializer_field 或 serializer 作为附加参数来调用 call 方法。

requires_context = True
def __call__(self, value, serializer_field):
    ...