SilentDev
SilentDev

Reputation: 22747

Customizing ModelSerializer error message is being ignored

This is my UserSerializer (I'm using the default Django User model):

class UserSerializer(SetCustomErrorMessagesMixin, serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
            super(UserSerializer, self).__init__(*args, **kwargs) # call the super() 
            for field in self.fields: # iterate over the serializer fields
                self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field
                self.fields[field].error_messages['null'] = 'Enter a valid %s.'%field

                # class CharField(Field) errors
                self.fields[field].error_messages['blank'] = 'Enter a valid %s.'%field
                self.fields[field].error_messages['max_length'] = '%s cannot have more than {max_length} characters.'%field
                self.fields[field].error_messages['min_length'] = '%s cannot have less than {min_length} characters.'%field

    class Meta:
        model = User
        fields = ('username', 'password', 'email',)

The problem is, when a user inputs a username which is too long, the error message is

"Username is too long."

Where is this error message coming from? I overwrote the "max_length" error message in the code above, but it does not show it. When I delete this line from my UserSerialzer:

self.fields[field].error_messages['max_length'] = '%s cannot have more than {max_length} characters.'%field

then the error message is:

"Ensure this field has no more than 30 characters."

which makes sense beause it is coming from the CharField DRF source code here: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py

But where is "Username is too long." coming from and how come it does not say "Username cannot have more than {max_length} characters." instead?

Upvotes: 3

Views: 1993

Answers (1)

Ivan
Ivan

Reputation: 6013

The problem appears to be that DRF adds validators for fields during their construction and copies the error messages from field classes.

For example from rest_framework.fields.CharField.__init__:

if self.min_length is not None:
    message = self.error_messages['min_length'].format(min_length=self.min_length)
    self.validators.append(MinLengthValidator(self.min_length, message=message))

So at the moment you are overwriting the messages, they are already used in the validators.

I think you can just create a yourapp.fields module where you subclass DRF serializer fields and override their default_error_messages, like so:

from rest_framework import fields

class CharField(fields.CharField):

    default_error_messages = {
        # Your messages
    }

And then just switch the module you import fields from.

You might also want to override __init__s to add field names in messages.

Upvotes: 2

Related Questions