Using out of the box fields in a serializer, validation error messages look something like this:
{
"product": [
"This field must be unique."
],
"price": [
"This field is required."
]
}
However, for the API I am writing, I would like to provide a unique error code for each failed validation, so that clients can programmatically respond to validation errors, or can provide their own custom messages in a UI. Ideally the error json would look something like this:
{
"product": [
{
"code": "unique",
"message": "This field must be unique."
}
],
"price": [
{
"code": "required",
"message": "This field is required."
}
]
}
The current approach using ValidationErrors makes this rather difficult. Looking through the code, it seems as though this type of error reporting is not supported currently. However, I'm looking for an approach to override the error handling to fit this model.
After opening the activation link in the web browser, the request is sent to the web application (Django Rest Framework). The web server compares the token from the activation URL with the token stored in the database. If they are the same, the email address is verified.
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.
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.
DRF enforces data validation in the deserialization process, which is why you need to call is_valid() before accessing the validated data. If the data is invalid, errors are then appended to the serializer's error property and a ValidationError is thrown. There are two types of custom data validators: Custom field.
This question was posted quite a while ago, so I will add the updated answer here. Newer versions of DRF now support this, but it still takes a bit of custom code. Creating a new exception handler with do the trick:
from rest_framework.views import exception_handler
from rest_framework.exceptions import APIException
def full_details_exception_handler(exc, context):
"""
This overrides the default exception handler to
include the human-readable message AND the error code
so that clients can respond programmatically.
"""
if isinstance(exc, APIException):
exc.detail = exc.get_full_details()
return exception_handler(exc, context)
Then configure DRF to use that custom handler in your settings:
REST_FRAMEWORK['EXCEPTION_HANDLER'] = 'my_module.full_details_exception_handler'
It would be nice if this configuration were available in DRF itself to just add it as a configuration option, but this is a pretty lightweight solution to include the error codes.
Add something like this to your serializer:
def is_valid(self, raise_exception=False):
try:
return super(ClientSerializer, self).is_valid(raise_exception)
except exceptions.ValidationError as e:
if 'email' in e.detail:
for i in range(len(e.detail['email'])):
if e.detail['email'][i] == UniqueValidator.message:
e.detail['email'][i] = {'code': 'not-unique'}
raise e
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