Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django rest framework: set field-level error from serializer validate() method

I have a serializer that validates fields based on the values of other fields, In the error response I would like to show each field error as a field error as opposed to showing everything under "non_field_errors" which is what would happen if I were to raise a ValidationError in the object-level validate method. Below is an illustration of what I'm trying to achieve:

MySerializer(ModelSerializer):     ...     def validate(self, data):         field_val1 = data['field_val1']         field_val2 = data['field_val2']         if not self._is_field_valid(field_val1, field_val2):             # The below line is how I would do what I want with Django             # Forms, however, it's not valid in DRF             self._errors['field_val1'] = 'this field is not valid' 

The desired error response is:

{'field_val1': ['this field is not valid']} 
like image 970
Jkk.jonah Avatar asked Jan 27 '15 20:01

Jkk.jonah


People also ask

How does Django validate data in serializer?

Validation in Django REST framework serializers is handled a little differently to how validation works in Django's ModelForm class. With ModelForm the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class.

How do you increase validation error in DRF?

The easiest way to change the error style through all the view in your application is to always use serializer. is_valid(raise_exception=True) , and then implement a custom exception handler that defines how the error response is created.

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


2 Answers

I figured it out, on this page of the documentation in the "BaseSerializer" section, there's an example that shows ValidationError can take a dictionary argument upon initialization.

If I raise ValidationError({'field_val1': ['this field is not valid']}) I get the JSON response I want.

like image 112
Jkk.jonah Avatar answered Sep 22 '22 01:09

Jkk.jonah


Similarly to the answer by @Jkk.jonah, this raises a ValidationError, but it reuses the original exception text without need to re-implement translations:

try:     serializer.fields['field_val1'].fail('required') except ValidationError as exc:     raise ValidationError({         'field_val1': exc.detail,     }) 

By default (i.e. on rest_framework.fields.Field class), available keys are:

default_error_messages = {     'required': _('This field is required.'),     'null': _('This field may not be null.') } 

Subclasses can add their own error messages there (and Serializer is a subclass of Field).

BTW, new error messages will be automagically merged with existing (inherited) messages - won't be overridden as might be expected.

like image 31
frnhr Avatar answered Sep 23 '22 01:09

frnhr