Convert Django Validation Errors to DRF compatible Errors

Convert Django Validation Errors to DRF compatible Errors

Custom Exception handler for Django Rest Framework

Django The Right Way's photo
Django The Right Way
ยทMar 9, 2022ยท

2 min read

Subscribe to my newsletter and never miss my upcoming articles

While working with Django+Django Rest Framework, you might have come up in a problem that occurrence of Errors/ValidationErrors from Django Model or some internals will not response a valid json your API consumer was expecting.

For example: Errors/ValidationErrors from Django Model or some internals will output something like

django-error-debug-mode-example.png

This looks so ugly (on debug mode only!), but with DEBUG=False as well, you will get something like

500-error-example.png

So, let's create up a custom exception handler for Django Rest Framework which will catch exceptions from those above mentioned scenarios and convert them to something much more prettier which can be easily transformed to json

from django.core.exceptions import NON_FIELD_ERRORS as DJ_NON_FIELD_ERRORS
from django.core.exceptions import ValidationError as DjValidationError
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.views import api_settings
from rest_framework.views import exception_handler as drf_exception_handler

DRF_NON_FIELD_ERRORS = api_settings.NON_FIELD_ERRORS_KEY


def handle(exc, context):
    # translate django validation error which ...
    # .. causes HTTP 500 status ==> DRF validation which will cause 400 HTTP status
    if isinstance(exc, DjValidationError):
        data = exc.message_dict
        if DJ_NON_FIELD_ERRORS in data:
            data[DRF_NON_FIELD_ERRORS] = data[DJ_NON_FIELD_ERRORS]
            del data[DJ_NON_FIELD_ERRORS]

        exc = DRFValidationError(detail=data)

    return drf_exception_handler(exc, context)

and add this exception handler function as your default exception handler on django rest framework settings on your settings.py file

REST_FRAMEWORK = {
     # .....
    'EXCEPTION_HANDLER': 'path_to_your_exception_hander'
     # ...
}

Now, the internal Django validation error that you raise from models or anywhere maybe will look like this;

error-400-bad-request.png

Tested on

  • Django(3.0.3) and Django Rest Framework(3.11.0)
  • Django(4.0.2) and Django Rest Framework(3.13.1)