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")}}
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".
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With