4

似乎 Django 1.9 中的错误电子邮件比以前长得多。我认为有一整节“设置”是多余的,而且可能过于暴露。

编辑 Django 发送的错误电子邮件的最佳方法是什么?

编辑:我不只是想隐藏敏感信息。Django 1.9 的电子邮件中有更多内容,我想将电子邮件的格式更改为更短。我喜欢它的旧方式。

4

2 回答 2

7

django 调试视图中有一个 django 模板变量TECHNICAL_500_TEMPLATE/ ,它控制错误报告中可见的内容,当然还有错误电子邮件。注释说明模板位于 python 变量中,以便在模板加载器中断的情况下生成错误。您可以在 django 包中更改此变量,但我不建议这样做。由同一文件中的类引用。TECHNICAL_500_TEXT_TEMPLATETECHNICAL_500_TEMPLATEExceptionReporter

django utils 日志AdminEmailHandler中的类然后使用生成 html 错误报告。ExceptionReporter

您可以子类化AdminEmailHandler并覆盖该emit函数以包含ExceptionReporter使用您自己定义的子类化版本TECHNICAL_500_TEMPLATE

这是一个例子:

创建reporter.py

from copy import copy

from django.views import debug
from django.utils import log
from django.conf import settings
from django import template

TECHNICAL_500_TEMPLATE = """
    # custom template here, copy the original and make adjustments
"""
TECHNICAL_500_TEXT_TEMPLATE = """
    # custom template here, copy the original and make adjustments
"""

class CustomExceptionReporter(debug.ExceptionReporter):
    def get_traceback_html(self):
        t = debug.DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE)
        c = template.Context(self.get_traceback_data(), use_l10n=False)
        return t.render(c)

    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)

class CustomAdminEmailHandler(log.AdminEmailHandler):
    def emit(self, record):
        try:
            request = record.request
            subject = '%s (%s IP): %s' % (
                record.levelname,
                ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS
                 else 'EXTERNAL'),
                record.getMessage()
            )
        except Exception:
            subject = '%s: %s' % (
                record.levelname,
                record.getMessage()
            )
            request = None
        subject = self.format_subject(subject)

        no_exc_record = copy(record)
        no_exc_record.exc_info = None
        no_exc_record.exc_text = None

        if record.exc_info:
            exc_info = record.exc_info
        else:
            exc_info = (None, record.getMessage(), None)

        reporter = CustomExceptionReporter(request, is_email=True, *exc_info)
        message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text())
        html_message = reporter.get_traceback_html() if self.include_html else None
        self.send_mail(subject, message, fail_silently=True, html_message=html_message)

然后只需将您的 django 设置设置为在日志记录部分中使用您的新处理程序。

LOGGING = {
    # Your other logging settings
    # ...
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'project.reporter.CustomAdminEmailHandler',
            'filters': ['special']
        }
    },
}

如果您只想隐藏设置,您可以注释掉第'settings': get_safe_settings(),294 行,如果您覆盖并复制粘贴def get_traceback_data(self):到您的CustomExceptionReporter

于 2016-04-03T09:10:25.123 回答
3

对于现在仍在寻找答案的人:

在 django 3.0 中,他们添加了选项来添加reporter_class自定义电子邮件正文和回溯文本呈现的选项。

因此,如果您只是想更改电子邮件模板,则无需同时覆盖AdminEmailHandler.

所以根据@Airith的回答,你需要:

# 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)

然后在您的日志配置中:

'handlers': {
        'mail_admins': {
             'level': 'ERROR',
             'class': 'django.utils.log.AdminEmailHandler',
             'include_html': False,
             'reporter_class': 'project.custom_exception_reporter.CustomExceptionReporter'
        },

两个注意事项:

  1. 如果您还希望以 HTML 格式发送电子邮件正文,则需要另一个模板 - TECHNICAL_500_TEMPLATE,新功能 - get_traceback_html(),并include_html = True在日志配置中进行设置。同样在这里,您应该复制 django 的默认模板并更改您需要的内容。
  2. 如果您不想将整个模板保存在该文件中,而是保存在不同的 .html 文件中,请注意,即使您将其放在您定义的模板目录中,它也不会找到它。我通过将 template.html 文件与自定义记者 .py 文件保存在同一目录中来解决它。

我的 custom_exception_report.py 示例,我将模板保存在同一目录中(如注释 #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())

您可以在此处阅读有关 django 文档中报告类的更多信息

于 2020-01-15T23:23:25.307 回答