Django AdminEmailHandler: Exception while resolving variable 'exception_type' in template 'unknown

Viewed 107

I'm trying to get the admin error emails to work in Django REST.

My logging configuration is like this:

    'loggers': {
        'django': {
            'handlers': ['console', 'logfile', 'mail_admins'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },

When 'mail_admins' is included as a handler, if I try to throw an error on a view like this:

@api_view()
def index(request):
    a = 2/0

The division by zero error is thrown (as expected), but then I get another error and a long traceback that starts like this:

DEBUG 2022-03-09 00:22:45,984 base 58083 123145391022080 Exception while resolving variable 'exception_type' in template 'unknown'.
Traceback (most recent call last):
  File "/path/to/.venv/lib/python3.10/site-packages/django/template/base.py", line 875, in _resolve_lookup
    current = current[bit]
  File "/path/to/.venv/lib/python3.10/site-packages/django/template/context.py", line 83, in __getitem__
    raise KeyError(key)
KeyError: 'exception_type'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/.venv/lib/python3.10/site-packages/django/template/base.py", line 881, in _resolve_lookup
    if isinstance(current, BaseContext) and getattr(
AttributeError: type object 'Context' has no attribute 'exception_type'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/path/to/.venv/lib/python3.10/site-packages/django/template/base.py", line 891, in _resolve_lookup
    current = current[int(bit)]
ValueError: invalid literal for int() with base 10: 'exception_type'
1 Answers

I believe you need a Django REST framework Custom Exception Handler

This is the one I personally use.

import traceback

from django.core.mail import mail_admins
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.views import exception_handler


def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc, context)

    if not isinstance(exc, AuthenticationFailed):
        mail_admins(
            "API - Exception",
            "Path: %s\nUser: %s%s\n\n%s"
            % (
                context["request"].get_full_path(),
                context["request"].user,
                (
                    "\nData: %s" % context["request"].data
                    if context["request"].data
                    else ""
                ),
                traceback.format_exc(),
            ),
        )

    return response

Don't forget to update your settings.py

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
Related