[Django]-Custom error messages in Django Rest Framework serializer

61👍

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"}}

28👍

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

26👍

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.

16👍

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.

6👍

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

5👍

I just spent an hour ripping my hair out over this, so figured I’d post an update here in case anyone else finds it useful.

I’m using djangorestframework version 3.10.3, and for whatever reason, it seems that drf no longer uses the ‘required’ key in the error_messages dict to allow customization of an error message for a missing value. Instead it uses ‘blank’.

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

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

4👍

DRF3.0 expects us to explicitly define the validators for fields if we wish to override the default model validators. This can be done by passing extra_kwargs and explicitly defining the validators for whichever field
you seem necessary. Also you can even specify your own custom validator which can be reused again for different fields or even other serializers

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

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

# my_app/validators.py
def validate_required(value):
    # whatever validation logic you need
    if value == '' or value is None:
        raise serializers.ValidationError('This field is required.')

# my_app/serializers.py
class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        extra_kwargs = {"field1": {"validators": [validators.validate_required,]}}

0👍

Just a note since I played with this for awhile, if you’re using something like a URLField that just adds a URLValidator, it doesn’t seem to use the error_messages, so I did something similar to @Hugo’s answer:

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

0👍

You can create separate function in serializers.py and call it from serializer class

def checkFields(fields):
    for field in fields:
        fields[field].error_messages['blank']=fields[field].error_messages['required'] = 'Please enter %s'%field

-1👍

This is the code that inherits the model’s error message.
There is also a module, so download it if you want.
If there’s a problem, leave it in the comments.

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
👤gongul

Leave a comment