【问题标题】:Django Rest Framework custom validation errorsDjango Rest Framework 自定义验证错误
【发布时间】:2015-03-17 18:31:06
【问题描述】:

我正在尝试为帐户模型自定义 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

长度验证工作正常,但从未抛出“密码为空”验证,因为之前抛出了默认错误(“密码”,[u'此字段可能不是空白。'])。

是否有任何选项可以禁用默认错误或首先通过我的自定义函数强制验证?

感谢您的帮助!

【问题讨论】:

    标签: validation field django-rest-framework


    【解决方案1】:

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

    在您的情况下,您希望实现两条错误消息: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', )
    

    我已将密码字段上的len 支票替换为the min_length argument

    这会将您的所有验证卸载到 Django REST 框架,这将使将来的升级更容易。如果您需要额外的自定义验证,您仍然可以覆盖 validate_password,但现在我已将其删除,因为它将为空。

    【讨论】:

    【解决方案2】:

    找到解决办法:

    我必须使用 to_internal_value 函数验证值,因为验证是以特定顺序运行的(感谢 Kevin Brown): order of validation

    现在我改进的代码如下:

    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_emtpy_valuesrun_validation函数中to_internal_value之前在source code中执行
    • @soooooot serializer.to_internal_value 应该在 serializer.run_validation 之前调用。我更新了order of validation answer 以包含指向源代码的链接,因此您可以跟踪调用。