For people still looking for an answer now:
In django 3.0 they added the option to add reporter_class which customize just the email body, and the traceback text rendering.
So, If you're just looking to change the email template, there's no need to also override the AdminEmailHandler.
so based on @Airith answer, you need to have:
# custom_exception_reporter.py
from django.views import debug
from django import template
TECHNICAL_500_TEXT_TEMPLATE = """
# custom template here, copy the original and make adjustments
"""
class CustomExceptionReporter(debug.ExceptionReporter):
def get_traceback_text(self):
t = debug.DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE)
c = template.Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
return t.render(c)
and then in your log config:
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'include_html': False,
'reporter_class': 'project.custom_exception_reporter.CustomExceptionReporter'
},
Two notes:
- If you wish to also send the email body as HTML, you need to have another template -
TECHNICAL_500_TEMPLATE, new function - get_traceback_html(), and set include_html = True in the log configuration. Also here you should copy django's default template and just change what you need.
- If you don't want to save the entire template in that file, but in a different .html file, notice that even if you will place it inside the template dir you defined, it will not find it.
I solved it by keeping the template.html file in the same dir with
the custom reporter .py file.
example of my custom_exception_report.py, where I keep the template in the same directory (as described in note #2):
import os
from django.views import debug
from django import template
TECHNICAL_500_TEXT_TEMPLATE = "technical_500.text"
class CustomExceptionReporter(debug.ExceptionReporter):
def get_traceback_text(self):
t = self._get_template(TECHNICAL_500_TEXT_TEMPLATE)
c = template.Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
return t.render(c)
@staticmethod
def _get_template(template_name):
dir_path = os.path.dirname(os.path.realpath(__file__))
template_path = os.path.join(dir_path, template_name)
with open(template_path, 'r') as fh:
return debug.DEBUG_ENGINE.from_string(fh.read())
You can read more about the report class in django docs here