Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django custom exception to return 503 and skip sending admin email

I want to raise a custom exception that will:

  • return 503 status
  • not send Django admin email

I can do one of them, but not both together:

  • return 503 status: by using DRF APIException, or custom exception handler to handle response, but I won't get the exception type in the logging record to filter.
  • not send email: by checking exception type in a custom email handler class, but this returns 500.

Code example of 503 handling by adding a custom middleware:

class CustomMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        if isinstance(exception, MyCustomException):
            return JsonResponse({"detail": "Error try later"}, status=503)

Code example to not send email:

class CustomAdminEmailHandler(AdminEmailHandler):
    def emit(self, record):
        ...
        reporter = ExceptionReporter(request, is_email=True, *exc_info)
        if reporter.exc_type and issubclass(reporter.exc_type, MyCustomException):
            return

Django sends email for any 5xx status response. When I use the middleware, I can't filter on reporter.exc_type since there's no exceptions trace (exc_info) anymore as the exception was handled in the process_exception.

like image 616
Def Soudani Avatar asked Sep 13 '25 13:09

Def Soudani


1 Answers

Attach exc_info to request in CustomMiddleware and access it in CustomAdminEmailHandler.

class CustomMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        if isinstance(exception, MyCustomException):
            # For CustomAdminEmailHandler      # Add this
            request.exc_info = sys.exc_info()  # Add this
            return JsonResponse({"detail": "Error try later"}, status=503)
class CustomAdminEmailHandler(log.AdminEmailHandler):
    def emit(self, record):
        request = record.request
        if record.exc_info:
            exc_info = record.exc_info
        elif hasattr(request, 'exc_info'):  # Add this
            # From CustomMiddleware         # Add this
            exc_info = request.exc_info     # Add this
        else:
            exc_info = (None, record.getMessage(), None)
        reporter = ExceptionReporter(request, is_email=True, *exc_info)
        if reporter.exc_type and issubclass(reporter.exc_type, MyCustomException):
            return
like image 134
aaron Avatar answered Sep 15 '25 08:09

aaron