Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom error messages in Django Rest Framework serializer

The scenario is quite straight-forward:

I have a model with some fields that are required. Let's say one of them is a TextField which can't be blank. I also have a ModelSerializer (Django Rest Framework) that represents that model.

When an empty string is used to set that field through the serializer the error returned comes from the model itself (This field can't be blank).

I would like to override the error messages only in the serializer level, without the need to explicitly re-specifying every field in the serializer (which I believe is against the DRY principle), having to write a validate_ method for each field and raise my own ValidationError or having to change the error messages in the Model level (because sometimes the context of the error message matters to my use-case and the error message should be given accordingly).

In other words, is there a way to override error messages in the serializer level as easy as it is for a 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")}} 
like image 612
Gabriel Amram Avatar asked Nov 15 '14 08:11

Gabriel Amram


People also ask

How do I increase error in Django REST framework?

The generic views use the raise_exception=True flag, which means that you can override the style of validation error responses globally in your API. To do so, use a custom exception handler, as described above. By default this exception results in a response with the HTTP status code "400 Bad Request".

How do I pass Queryset to serializer?

To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.

How do you pass extra context data to Serializers in Django REST framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.


2 Answers

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"}} 
like image 116
Gabriel Amram Avatar answered Oct 25 '22 20:10

Gabriel Amram


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.

like image 22
mariodev Avatar answered Oct 25 '22 20:10

mariodev