Global exception handling under Django and DRF(Django Rest Framework)

All good things must come to an end.

Django is often used in combination with DRF in web development. DRF has its own set of exception handling mechanism. We can globally intercept the exceptions thrown in DRF, such as returning a unified json format for processing in the foreground.
However, while using the background admin to manage data in Django, we don't want to modify the original exception return. Therefore, we need to configure the global exceptions of Django and DRF to meet our needs.

Anomaly type

When writing code, we usually encounter the following two types of exceptions:

  • [known exceptions] predictable exceptions, most of which are thrown manually during programming.
  • [unknown exception] an exception that we are completely unaware of, such as an exception caused by some calculation errors.

Exception return format

For exceptions in Django admin, we still maintain the original return format. For other exceptions, we want to return the following json format to the front end for unified capture.

{
    "msg": "Sorry, ,we made a mistake!", 
    "error_code": 1000, 
    "request": "url"
}

Abnormal source

We can roughly divide the sources of exceptions in the program into the following types:

  • Exceptions of APIException type thrown by APIView and its subclasses that inherit DRF
  • Exception thrown by Django admin
  • Other programs run abnormally

Define global exception handling

We can first define a Django middleware to capture "exceptions thrown by Django admin" and "other program running exceptions",
We can judge whether it is an exception of Django admin through the request path. If so, we will directly return None, that is, throw it according to the original format,
If it is not, we will return the exception in json format.

class ExceptionGlobeMiddleware(MiddlewareMixin):
    """
        Below is the global exception handler of django
    """

    def process_exception(self, request, exception):
        # Throw the django admin exception directly
        if str(request.path).startswith('/admin/'):
            return None

        # Catch other exceptions and return 500 directly
        ex_data = {
            "msg": "Sorry, we make a mistake (* ̄︶ ̄)!",
            "error_code": 1000,
            "request": request.path
        }
        return JsonResponse(data=ex_data, status=500)

Don't forget to add Middleware in Django setting.

Then we define the global exception capture of DRF and call the exception of the parent class_ If the response returned after the handler method is not None, it indicates that it is an APIException type,
At this time, we return the exception format defined by ourselves. If it is None, we directly return None. At this time, it will be caught by the exceptionglobalmiddleware defined by Django, and it will still be sent to the client
Return the json format defined by yourself.

def globe_exception_handler(exc, context):
    """
        Below is the global exception handler of drf
        Http404 / PermissionDenied / APIException
    """

    # Call REST framework's default exception handler
    response = exception_handler(exc, context)
    request = context['request']

    # print exception to console
    print(traceback.format_exc())

    # Now add the HTTP status code to the response.
    if response is not None:
        if isinstance(response.data, list):
            msg = '; '.join(response.data)
        elif isinstance(response.data, str):
            msg = response.data
        else:
            msg = 'Sorry, we make a mistake (* ̄︶ ̄)!'

        ex_data = {
            "msg": msg,
            "error_code": 1000,
            "request": request.path
        }
        return JsonResponse(data=ex_data, status=response.status_code)

    # If the response is None, the above exceptionglobalmiddleware will be triggered directly
    return response

Here, the unified global exception handling of Django combined with DRF is configured.

REFERENCE

[1] Python Django, middleware, middleware functions, global exception handling: https://blog.csdn.net/houyanhua1/article/details/85028983
[2] Django DRF global exception handling: https://zhuanlan.zhihu.com/p/288814772
[3] Handling of all exceptions captured by Django: https://blog.csdn.net/huangqiang1363/article/details/106472203/
[4] Django rest framework custom Exception: https://www.cnblogs.com/ifykwf/p/7054790.html
[5] Django rest framework custom return data format: https://www.jianshu.com/p/c0be24752584
[6] Exception handling exceptions in Django: https://www.cnblogs.com/itBlogToYpl/articles/11844547.html
[7] django rest framework exception capture: https://blog.csdn.net/weixin_46105038/article/details/117228013
[8] Global configuration of Django rest framework exception capture: https://blog.csdn.net/Mr_w_ang/article/details/85017583
[9] Exception handling in REST framework views: https://www.django-rest-framework.org/api-guide/exceptions/

Tags: Python Django Back-end RESTful

Posted on Fri, 15 Oct 2021 13:44:19 -0400 by echion