from django.http import Http404 import logging from rest_framework.exceptions import APIException, status from rest_framework.response import Response from rest_framework.views import set_rollback, exception_handler class HealthcheckException(APIException): """Exception class used for when the application's health check fails""" pass class DeisException(APIException): status_code = 400 class AlreadyExists(APIException): status_code = 409 class Conflict(AlreadyExists): pass class UnprocessableEntity(APIException): status_code = 422 class ServiceUnavailable(APIException): status_code = 503 default_detail = 'Service temporarily unavailable, try again later.' def custom_exception_handler(exc, context): # give more context on the error since DRF masks it as Not Found if isinstance(exc, Http404): set_rollback() return Response(str(exc), status=status.HTTP_404_NOT_FOUND) # Call REST framework's default exception handler after specific 404 handling, # to get the standard error response. response = exception_handler(exc, context) # No response means DRF couldn't handle it # Output a generic 500 in a JSON format if response is None: logging.exception('Uncaught Exception', exc_info=exc) set_rollback() return Response({'detail': 'Server Error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # log a few different types of exception instead of using APIException if isinstance(exc, (DeisException, ServiceUnavailable, HealthcheckException)): logging.exception(exc.__cause__, exc_info=exc) return response