Django Rest Framework序列化程序中的自定义错误消息

时间:2014-11-15 08:18:23

标签: django django-rest-framework

情景非常简单:

我有一个模型,其中包含一些必填字段。我们说其中一个是TextField,不能是blank。 我还有一个代表该模型的ModelSerializer(Django Rest Framework)。

当使用空字符串通过序列化程序设置该字段时,返回的错误来自模型本身(This field can't be blank)。

我想仅在序列化程序级别覆盖错误消息,而无需显式重新指定序列化程序中的每个字段(我认为这违反了DRY原则),必须编写validate_每个字段的方法,并引发我自己的ValidationError或必须更改Model级别的错误消息(因为有时错误消息的上下文对我的用例很重要,应该给出错误消息相应地)。

换句话说,有没有办法在序列化程序级别覆盖错误消息,就像ModelForm一样简单:

class MyModelForm(ModelForm):
    class Meta:
        model = MyModel
        error_messages = {"field1": {"required": _("For some reason this is a custom error message overriding the model's default")}}

9 个答案:

答案 0 :(得分:24)

编辑:我看到这个问题仍然会收到一些观点,因此请务必注意另一种方法,比我在此处发布的原始答案要清晰得多。

您可以使用序列化程序的Meta类的extra_kwargs属性,如下所示:

class UserSerializer(ModelSerializer):

    class Meta:
        model = User
        extra_kwargs = {"username": {"error_messages": {"required": "Give yourself a username"}}}

原始回答:

使用@mariodev的回答我在我的项目中创建了一个新类:

from rest_framework.serializers import ModelSerializer, ModelSerializerOptions

class CustomErrorMessagesModelSerializerOptions(ModelSerializerOptions):
    """
    Meta class options for CustomErrorMessagesModelSerializerOptions
    """
    def __init__(self, meta):
        super(CustomErrorMessagesModelSerializerOptions, self).__init__(meta)
        self.error_messages = getattr(meta, 'error_messages', {})

class CustomErrorMessagesModelSerializer(ModelSerializer):
    _options_class = CustomErrorMessagesModelSerializerOptions

    def __init__(self, *args, **kwargs):
        super(CustomErrorMessagesModelSerializer, self).__init__(*args, **kwargs)

        # Run through all error messages provided in the Meta class and update
        for field_name, err_dict in self.opts.error_messages.iteritems():
            self.fields[field_name].error_messages.update(err_dict)

第一个可以像Meta一样向序列化程序添加新的ModelForm类属性。 第二个继承自ModelSerializer并使用@ mariodev技术更新错误消息。

只剩下一切,只是继承它,并做类似的事情:

class UserSerializer(CustomErrorMessagesModelSerializer):
    class Meta:
        model = User
        error_messages = {"username": {"required": "Give yourself a username"}}

答案 1 :(得分:18)

在序列化程序中:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User

    def __init__(self, *args, **kwargs):
        super(UserSerializer, self).__init__(*args, **kwargs)

        self.fields['username'].error_messages['required'] = u'My custom required msg'

请注意,某些错误消息包含%s占位符,例如:

'invalid': _("'%s' value must be either True or False."),

代表BooleanField

因此,您需要在DRF fields.py中的每个字段类型中查看default_error_messages部分,才能正确使用它。

答案 2 :(得分:10)

unique似乎被error_messages忽略了,所以我不得不采取不同的方法。

email = serializers.EmailField(validators=[
    UniqueValidator(
        queryset=models.Client.objects.all(),
        message="My custom error",
    )]
)

它比@ gabriel-amram更简单(但更不灵活,更不可重复使用),但远不如@ mariodev那么简单。

答案 3 :(得分:4)

UniqueValidator的另一种方法(与ModelSerializer一起使用):

def __init__(self, *args, **kwargs):
    super(UserSerializer, self).__init__(*args, **kwargs)
    # Find UniqueValidator and set custom message
    for validator in self.fields['email'].validators:
        if isinstance(validator, validators.UniqueValidator):
            validator.message = _('This email already exist on this site')

答案 4 :(得分:2)

我试图创建一个简单的Serializer而不是ModelSerializer。可能是因为这样,Gabriel Amram接受extra_kwargs接受的答案对我没有用。 @mariodev的另一个最佳答案确实起作用了,但我正在寻找一种更优雅的解决方案,并找到了一个。事实证明Field类接受error_messages作为参数,这是一个覆盖默认错误消息的字典。这是reference to the docs。与接受的答案中所述的格式相同。这是一个示例:

from rest_framework import serializers

class MySerializer(serializers.Serializer):
    client_id = serializers.IntegerField(required=True, error_messages={'required': 'Custom error message'})

答案 5 :(得分:1)

我刚刚花了一个小时将头发扯掉,所以想在其他人觉得有用的情况下在这里发布更新。

我正在使用djangorestframework版本3.10.3,无论出于何种原因,看来drf不再使用error_messages字典中的“ required”键来允许为缺少的值定制错误消息。相反,它使用“空白”。

class SampleSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = SampleModel
        fields = (
            'description',
        )

        extra_kwargs = {
            'description': {'error_messages': {'blank': "Please provide a description"}},
        }

答案 6 :(得分:0)

自从我玩了一段时间以来只是一个注释,如果你使用像URLField那样只添加一个URLValidator,它似乎没有使用error_messages,所以我做了类似于@的事情。雨果的回答:

class Meta:
    extra_kwargs = {"url_field": {"validators": [validators.URLValidator(message="My error message")]}}

答案 7 :(得分:0)

如果我们希望覆盖默认的模型验证器,DRF3.0希望我们明确定义字段的验证器。这可以通过传递extra_kwargs并为任何字段显式定义验证器来完成 你似乎有必要。您甚至可以指定自己的自定义验证器,可以再次为不同的字段或其他序列化器重复使用

http://www.django-rest-framework.org/api-guide/serializers/#validation

http://www.django-rest-framework.org/api-guide/validators/#validation-in-rest-framework

top: scrollTop < originalY
   ? 0
   : scrollTop - originalY + topMargin

答案 8 :(得分:-1)

这是继承模型错误信息的代码。
还有一个模块,所以如果你想下载它。 如果有问题,请在评论中留言。

https://pypi.org/project/django-rest-inherits-error-messages/#files

from rest_framework import serializers
from rest_framework.relations import HyperlinkedRelatedField
from rest_framework.utils.field_mapping import get_nested_relation_kwargs

class InheritsModelSerializer(serializers.ModelSerializer):
    def build_field(self, field_name, info, model_class, nested_depth):
        '''
        inherits the error_messages of the model
        '''
        result: tuple = super().build_field(field_name, info, model_class, nested_depth)

        field = model_class._meta.get_field(field_name)
        error_messages = field.error_messages

        if error_messages:
            result[1]['error_messages'] = field.error_messages

        return result