Custom error messages in Django Rest Framework serializer

EDIT: I see that this question still receives some views, so it is important to note that there's another approach, much cleaner than the original answer I posted here.

You can just use the extra_kwargs attribute of the serializer's Meta class, like so:

class UserSerializer(ModelSerializer):

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

Original answer:

Using @mariodev 's answer I created a new class in my project that does that:

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)

The first one gives the possibility to add a new Meta class attribute to the serializer as with the ModelForm. The second one inherits from ModelSerializer and uses @mariodev's technique to update the error messages.

All is left to do, is just inherit it, and do something like that:

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

In your serializer:

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'

Please notice that some error messages consist of %s placeholders like:

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

for BooleanField.

So you need to go over default_error_messages part in each field type in the DRF's fields.py, to use it properly.


I tried to create a simple Serializer rather than a ModelSerializer. Probably because of that the accepted answer with extra_kwargs by Gabriel Amram didn't work for me. Another top answer by @mariodev did work but I was looking for a more elegant solution and found one. Turns out that the Field class accepts error_messages as a parameter, which is a dictionary that overrides the default error messages. Here is the reference to the docs. It's the same format as described in the accepted answers. Here is an example:

from rest_framework import serializers

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

unique seemed to be ignored from error_messages, so I had to take a different approach.

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

It's simpler (yet less flexible, less reusable) than @gabriel-amram's, but far less hacky than @mariodev's.


Another approach for UniqueValidator (for using with 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')