Skip to main content

报告错误

当您运行公共网站时,应始终关闭 DEBUG 设置。这将使您的服务器运行得更快,还将防止恶意用户看到您的应用程序的错误页面可以揭示的详细信息。

但是,将 DEBUG 设置为 False 意味着您不会看到您的网站生成的错误 - 每个人只会看到您的公开错误页面。您需要跟踪部署的网站中发生的错误,因此可以将Django配置为创建包含有关这些错误的详细信息的报告。

电子邮件报告

服务器错误

DEBUGFalse 时,每当代码引发未处理的异常并导致内部服务器错误(HTTP状态代码500)时,Django将向 ADMINS 设置中列出的用户发送电子邮件。这样,管理员可以立即通知任何错误。 ADMINS 将获得错误的描述,完整的Python跟踪,以及导致错误的HTTP请求的详细信息。

注解

为了发送电子邮件,Django需要一些设置告诉它如何连接到您的邮件服务器。至少,您需要指定 EMAIL_HOST 以及可能的 EMAIL_HOST_USEREMAIL_HOST_PASSWORD,但根据邮件服务器的配置,还可能需要其他设置。有关电子邮件相关设置的完整列表,请咨询 Django设置文档

默认情况下,Django会从 root@localhost 发送电子邮件。但是,某些邮件提供商会拒绝来自此地址的所有电子邮件。要使用不同的发件人地址,请修改 SERVER_EMAIL 设置。

要激活此行为,请将收件人的电子邮件地址放在 ADMINS 设置中。

参见

服务器错误电子邮件使用日志记录框架发送,因此您可以通过 自定义您的日志配置 自定义此行为。

404错误

Django也可以配置为电子邮件关于损坏的链接的错误(404“page not found”错误)。在以下情况下,Django会发送有关404错误的电子邮件:

如果满足这些条件,每当您的代码引发404并且请求具有引用程序时,Django将向 MANAGERS 设置中列出的用户发送电子邮件。它不打扰发送电子邮件给没有引荐来源网址的404,这些通常只是输入破碎的网址或破坏的网络僵尸的人。当引用程序等于请求的URL时,它也忽略404s,因为这种行为也来自破坏的Web bots。

Changed in Django 1.9:

在旧版本中,当引荐来源网址等于请求的网址时,系统不会忽略404。

注解

BrokenLinkEmailsMiddleware 必须出现在拦截404错误的其他中间件之前,例如 LocaleMiddlewareFlatpageFallbackMiddleware。将其放在 MIDDLEWARE 设置的顶部。

您可以通过调整 IGNORABLE_404_URLS 设置来告诉Django停止报告特定404。它应该是已编译的正则表达式对象的列表。例如:

import re
IGNORABLE_404_URLS = [
    re.compile(r'\.(php|cgi)$'),
    re.compile(r'^/phpmyadmin/'),
]

在此示例中,404到以 .php.cgi 结尾的任何URL将报告 not。也不会以 /phpmyadmin/ 开头的任何网址。

以下示例说明了如何排除浏览器和抓取工具经常请求的某些常规网址:

import re
IGNORABLE_404_URLS = [
    re.compile(r'^/apple-touch-icon.*\.png$'),
    re.compile(r'^/favicon\.ico$'),
    re.compile(r'^/robots\.txt$'),
]

(请注意,这些是正则表达式,因此我们在句子前面放置一个反斜杠以转义它们。)

如果您想要进一步自定义 django.middleware.common.BrokenLinkEmailsMiddleware 的行为(例如,忽略来自Web爬网程序的请求),您应该对其进行子类化并覆盖其方法。

参见

使用日志记录框架记录404错误。默认情况下,这些日志记录被忽略,但您可以通过适当地编写处理程序和 配置日志记录 来使用它们进行错误报告。

过滤错误报告

警告

过滤敏感数据是一个困难的问题,几乎不可能保证敏感数据不会泄漏到错误报告中。因此,错误报告应该仅供可信任的团队成员使用,您应避免通过Internet(例如通过电子邮件)传输未加密的错误报告。

过滤敏感信息

错误报告对于调试错误非常有用,因此记录尽可能多关于这些错误的相关信息通常是有用的。例如,默认情况下,Django为引发的异常,每个 traceback frame 的局部变量和 HttpRequestattributes 记录 full traceback

然而,有时某些类型的信息可能太敏感,并且因此可能不适于跟踪例如用户的密码或信用卡号。因此,除了按照 DEBUG 文档中所述过滤出敏感的设置外,Django还提供了一组函数装饰器,以帮助您控制哪些信息应该从生产环境中的错误报告中过滤掉(即,DEBUG 是设置为 False):sensitive_variables()sensitive_post_parameters()

sensitive_variables(*variables)[源代码]

如果代码中的函数(视图或任何常规回调)使用易于包含敏感信息的局部变量,则可以防止这些变量的值包含在使用 sensitive_variables 装饰器的错误报告中:

from django.views.decorators.debug import sensitive_variables

@sensitive_variables('user', 'pw', 'cc')
def process_info(user):
    pw = user.pass_word
    cc = user.credit_card_number
    name = user.name
    ...

在上述示例中,userpwcc 变量的值将被隐藏,并在错误报告中用星号(**********)替换,而 name 变量的值将被公开。

要从错误日志系统地隐藏函数的所有局部变量,请不要向 sensitive_variables 装饰器提供任何参数:

@sensitive_variables()
def my_function():
    ...

当使用多个装饰器

如果你想要隐藏的变量也是一个函数参数(例如在下面的例子中为“ user ”),并且如果修饰函数有多个修饰符,那么确保将 @sensitive_variables 放在修饰符链的顶部。这样,它也将隐藏函数参数,因为它通过其他装饰器:

@sensitive_variables('user', 'pw', 'cc')
@some_decorator
@another_decorator
def process_info(user):
    ...
sensitive_post_parameters(*parameters)[源代码]

如果您的一个视图接收到具有易受含有敏感信息的 POST parametersHttpRequest 对象,则可以防止这些参数的值包含在使用 sensitive_post_parameters 装饰器的错误报告中:

from django.views.decorators.debug import sensitive_post_parameters

@sensitive_post_parameters('pass_word', 'credit_card_number')
def record_user_profile(request):
    UserProfile.create(
        user=request.user,
        password=request.POST['pass_word'],
        credit_card=request.POST['credit_card_number'],
        name=request.POST['name'],
    )
    ...

在上面的示例中,pass_wordcredit_card_number POST参数的值将被隐藏,并在错误报告中的请求的表示中用星形(**********)替换,而 name 参数的值将被公开。

要在错误报告中系统地隐藏请求的所有POST参数,请不要向 sensitive_post_parameters 装饰器提供任何参数:

@sensitive_post_parameters()
def my_view(request):
    ...

对于某些 django.contrib.auth.views 视图(loginpassword_reset_confirmpassword_change,和 auth admin中的 add_viewuser_change_password),所有POST参数都系统地过滤出错误报告,以防止泄露敏感信息(例如用户密码)。

自定义错误报告

所有 sensitive_variables()sensitive_post_parameters() 分别使用敏感变量的名称注释修饰的函数,并使用敏感的POST参数的名称注释 HttpRequest 对象,以便以后在发生错误时将此敏感信息过滤出报告。实际的过滤是由Django的默认错误报告过滤器:django.views.debug.SafeExceptionReporterFilter。当生成错误报告时,此过滤器使用装饰器的注释将星形(**********)替换为相应的值。如果你想覆盖或自定义整个网站的默认行为,你需要定义自己的过滤器类,并告诉Django通过 DEFAULT_EXCEPTION_REPORTER_FILTER 设置使用它:

DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter'

您还可以通过设置 HttpRequestexception_reporter_filter 属性,以更精细的方式控制在任何给定视图中使用哪个过滤器:

def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_filter = CustomExceptionReporterFilter()
    ...

您的自定义过滤器类需要继承 django.views.debug.SafeExceptionReporterFilter,并可以覆盖以下方法:

class SafeExceptionReporterFilter[源代码]
SafeExceptionReporterFilter.is_active(request)[源代码]

返回 True 以激活在其他方法中操作的过滤。默认情况下,如果 DEBUGFalse,则过滤器处于活动状态。

SafeExceptionReporterFilter.get_post_parameters(request)[源代码]

返回已过滤的POST参数字典。默认情况下,它用星(**********)替换敏感参数的值。

SafeExceptionReporterFilter.get_traceback_frame_variables(request, tb_frame)[源代码]

返回给定回溯帧的已过滤的局部变量字典。默认情况下,它用星形(**********)替换敏感变量的值。

参见

您还可以通过编写自定义的 异常中间件 来设置自定义错误报告。如果你写的是自定义的错误处理,最好模拟Django的内置错误处理,只有当 DEBUGFalse 时才报告/记录错误。