Django Rest Framework自定义验证错误

8

我正在尝试为帐户模型自定义DRF(3.x)的默认验证错误。

我的目标是编写一个验证函数,以便发送定制的错误消息。

我尝试了以下内容:

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Account
        fields = ('id', 'email', 'password',)

    def validate_password(self, value):
        """
        Validate Password.
        """
        if not value:
            raise serializers.ValidationError("Password cannot be empty!")
        elif len(value) < 5:
            raise serializers.ValidationError("Password to short...")
        return value

长度验证可以正常工作,但是“密码为空”的验证从未被触发,因为默认错误('password',[u'此字段不能为空。'])会先被抛出。

有没有选项可以禁用默认错误或强制使用自定义函数进行验证?

谢谢帮助!

2个回答

8
您可以通过在初始化字段时设置"error_messages"参数,以在每个字段上覆盖验证错误。您需要传递一个字典,其中键是错误消息名称,值是错误消息的自定义文本。

在您的情况下,您希望实现两个错误消息:requiredmin_length 。您还可能需要覆盖blank ,除非您在该字段上设置了allow_blank=True

因此,通过这些更改,您的序列化程序将变为:

class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True,
        required=False,
        min_length=5,
        error_messages={
            "blank": "Password cannot be empty.",
            "min_length": "Password too short.",
        },
    )

    class Meta:
        model = Account
        fields = ('id', 'email', 'password', )

我已经在密码字段上使用了min_length参数,替代了您的长度检查。
这样做将所有验证工作转移到Django REST框架中,使得未来升级更加容易。如果您需要额外的自定义验证,仍然可以覆盖validate_password方法,但是暂时我已将其删除,因为它是空的。

谢谢你的回答!因为我想返回特定于语言的错误消息,所以我认为调用一个处理相同错误不同消息的函数会更好。有没有可能从error_message参数中调用一个函数? - Dario Behringer
我建议研究一下Django的翻译工具。这是DRF将用于翻译,我被告知它运行良好。另一个选择是覆盖异常处理程序并在那里手动进行翻译。 - Kevin Brown-Silva

5
发现了一个解决方案:
我需要使用to_internal_value函数对值进行验证,因为验证是按特定顺序运行的(感谢Kevin Brown):验证顺序 现在我的改进后的代码如下:
class AccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Account
        fields = ('id', 'email', 'password',)

    def to_internal_value(self, data):
        password = data.get('password')
        """
        Validate Password.
        """
        if not password:
            raise serializers.ValidationError({'password': 'Password cannot be empty!'})
        elif len(password) < 5:
            raise serializers.ValidationError({'password': 'Password to short...'})

        return {
            'password': password
        }

我希望这篇文章对某些人有所帮助 :)

为什么它能够工作呢?在 源代码 中,似乎 validate_empty_valuesrun_validation 函数中的 to_internal_value 之前被执行。 - soooooot
@soooooot 在调用 serializer.run_validation 之前应该先调用 serializer.to_internal_value。我已经更新了 order of validation answer,其中包含源代码链接,这样你就可以跟踪调用过程。 - Kevin Brown-Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接