Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global Exception Handling in Django-rest-framework

Is there a way to handle all the exceptions globally without using try-except block in django rest framework.

I want to convert html error page that django is throwing to a customised json object response.

I have created an exception.py file in my app

def custom_exception_handler(exc, context=None):
    response = exception_handler(exc)


    if isinstance(exc, HttpResponseServerError):  
        custom_response_data = { 
            'detail': 'Internal Server Error' # custom exception message
        }
        response.data = custom_response_data

    return response

i have configured this in settings.py.

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'EXCEPTION_HANDLER':'my_project.my_app.exceptions.custom_exception_handler'}
like image 852
Shubham Kumar Avatar asked Feb 27 '20 04:02

Shubham Kumar


People also ask

How do I handle exceptions in Django?

Custom exception handlingThe exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.

How do you handle exceptions in REST API?

To deal with exceptions, the recommended practice is to follow the sequence outlined below: Determine whether the REST API request succeeded or failed, based on the HTTP status response code returned. If the REST API request failed and the response is application/json, serialize the model.


1 Answers

Since I came across with a similar situation that lead me to this question, I'll answer following the original question that is related to Django Rest Framework specifically and not just Django.

I understand that you want to handle raised exceptions from your views, globally, without having to define try/except blocks on each view module.

DRF allows you to define your own Custom Exception Handling mechanism (docs). Here is an example:

At my_custom_except_handler.py:

import logging
from rest_framework.views import exception_handler
from django.http import JsonResponse
from requests import ConnectionError

def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first
    response = exception_handler(exc, context)

    # checks if the raised exception is of the type you want to handle
    if isinstance(exc, ConnectionError):
        # defines custom response data
        err_data = {'MSG_HEADER': 'some custom error messaging'}

        # logs detail data from the exception being handled
        logging.error(f"Original error detail and callstack: {exc}")
        # returns a JsonResponse
        return JsonResponse(err_data, safe=False, status=503)

    # returns response as handled normally by the framework
    return response

As stated in the docs, the defined response object refers to:

The exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.

In other words, 'response' won't be None only when handling these exceptions docs:

  • Subclasses of APIException.
  • Django's Http404 exception.
  • Django's PermissionDenied exception.

If your custom handler returns None, then the exception will be handled 'normally' by the framework, returning typical 500 server error.

Finally remember to set the required key at settings.py:

REST_FRAMEWORK = {'EXCEPTION_HANDLER': 
    'my_project.my_app.my_custom_except_handler.custom_exception_handler'}

Hope it helps!

like image 185
NicoE Avatar answered Sep 24 '22 07:09

NicoE