Rest-framework专栏讲解(十四):Validators

Rest-framework专栏讲解(十四):Validators而这个功能就可以通过验证类或者验证函数来实现。 用于 unique=True 的模型字段约束。 lookup:用于查找具有正在验证的值的现有实例的查找。默认为 “exact” 该验证类用于多字段下的组合约束。 该三个验证类用于时间模型字段的限制约束。 因为用于默认值的值在验证运…

MedusaSorcerer的博客


点击跳转到 Rest-Framework 专栏目录

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

示例说明:

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

CustomerReportSerializer 是 创建或更新 CustomerReportRecord 实例的基础 serializer:

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

使用 Django-shell 可以执行获取到以下信息:

>>> from project.example.serializers import CustomerReportSerializer
>>> serializer = CustomerReportSerializer()
>>> print(repr(serializer))
CustomerReportSerializer():
    id = IntegerField(label='ID', read_only=True)
    time_raised = DateTimeField(read_only=True)
    reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>])
    description = CharField(style={'type': 'textarea'})

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'
            )
        ]

serializer 上始终要求存在用于验证的日期字段, 不能简单地依赖模型类 default=…, 因为用于默认值的值在验证运行之后才会生成。

根据你希望 API 的行为方式, 您可能需要使用一些样式, 如果您正在使用 ModelSerializer, 那么您可能只需要依赖 REST framework 为您生成的默认值, 但是如果您使用的是 Serializer 或只是想要更显式的控制, 请使用下面演示的样式之一。

与可写日期字段一起使用

如果您希望日期字段可写, 则唯一需要注意的是您可以通过设置 default 参数或 required=True 来确保输入数据中的日期字段始终可用。

published = serializers.DateTimeField(required=True)

与只读日期字段一起使用

如果希望日期字段可见, 但用户不可编辑, 则设置 read_only=True 并另外设置一个 default=... 参数。

published = serializers.DateTimeField(read_only=True, default=timezone.now)

与隐藏的日期字段一起使用

如果您希望日期字段对用户完全隐藏, 请使用 HiddenField, 此字段类型不接受用户输入, 而是始终将其默认值返回给序列化器中的 validated_data

published = serializers.HiddenField(default=timezone.now)

默认值高级用法

CurrentUserDefault

可用于表示当前用户的默认类, 如果你想使用, 则需要在实例化序列化程序时, 'request' 必须作为上下文字典的一部分提供。

owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)

CreateOnlyDefault

在创建时用于默认值, 更新操作时将忽略该字段。

created_at = serializers.DateTimeField(
    default=serializers.CreateOnlyDefault(timezone.now)
)

复杂的验证

在某些验证不足以满足你的验证需求时, 显式验证将会是个很好的方案, 在 serializer 类中重写 validate 方法, 将会是个很不错的。

class BillingRecordSerializer(serializers.ModelSerializer):
    def validate(self, attrs):
        # Apply custom validation either here, or in the view.

    class Meta:
        fields = ['client', 'date', 'amount']
        extra_kwargs = {'client': {'required': False}}
        validators = []  # Remove a default "unique together" constraint.

自定义验证

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

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

当然, 你可以在你定义的 Serializer 中, 针对某一个字段进行特殊的验证, 如下:

class BillingRecordSerializer(serializers.ModelSerializer):
    def validate_title(self, attrs):
        # Apply custom validation either here, or in the view.

格式是在 Serializer 中定义添加 .validate_<field_name> 方法, 即可实现。

可以使用类的方式, 定义验证器, 重写 __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_fieldserializer 作为附加参数来调用 __call__ 方法。

requires_context = True

def __call__(self, value, serializer_field):
    ...

今天的文章Rest-framework专栏讲解(十四):Validators分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/22437.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注