如何管理错误报告

在运行公共站点时,您应该始终关闭 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“页面未找到”错误)的错误电子邮件。当以下条件满足时,Django 会发送有关 404 错误的电子邮件:

如果满足这些条件,则只要您的代码引发 404 并且请求具有引用者,Django 就会向 MANAGERS 设置中列出的用户发送电子邮件。对于没有引用者的 404,它不会发送电子邮件 - 这些通常是用户输入错误的 URL 或错误的 Web 机器人。当引用者等于请求的 URL 时,它也会忽略 404,因为此行为也来自错误的 Web 机器人。

注意

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

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

import re

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

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

以下示例显示了如何排除浏览器和爬虫通常请求的一些常规 URL

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 错误使用日志记录框架进行记录。默认情况下,这些日志记录被忽略,但您可以通过编写处理程序并 配置日志记录 来适当使用它们进行错误报告。

过滤错误报告

警告

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

过滤敏感信息

错误报告对于调试错误非常有帮助,因此通常很有用记录尽可能多的与这些错误相关的相关信息。例如,默认情况下,Django 会记录引发异常的 完整回溯、每个 回溯帧 的局部变量以及 HttpRequest属性

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

sensitive_variables(*variables)[source]

如果代码中的函数(视图或任何常规回调)使用可能包含敏感信息的局部变量,可以使用 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): ...
Django 5.0 中的更改

添加了对包装 async 函数的支持。

sensitive_post_parameters(*parameters)[source]

如果其中一个视图接收一个带有可能包含敏感信息的 HttpRequest 对象的 POST parameters,可以使用 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 管理中的 add_viewuser_change_password),系统会自动过滤掉错误报告中的所有 POST 参数,以防止泄露用户密码等敏感信息。

Django 5.0 中的更改

添加了对包装 async 函数的支持。

自定义错误报告

sensitive_variables()sensitive_post_parameters() 分别做的只是用敏感变量的名称来注释被装饰的函数,并用敏感 POST 参数的名称来注释 HttpRequest 对象,以便稍后在发生错误时可以从报告中过滤掉这些敏感信息。实际的过滤由 Django 的默认错误报告器过滤器完成:django.views.debug.SafeExceptionReporterFilter。此过滤器使用装饰器的注释,在生成错误报告时用星号 (**********) 替换相应的值。如果您希望覆盖或自定义整个站点的此默认行为,则需要定义自己的过滤器类,并通过 DEFAULT_EXCEPTION_REPORTER_FILTER 设置告诉 Django 使用它。

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[source]
cleansed_substitute

用于替换敏感值的字符串值。默认情况下,它用星号 (**********) 替换敏感变量的值。

hidden_settings

用于匹配被视为敏感的设置和 request.META 值的已编译正则表达式对象。默认情况下等效于

import re

re.compile(r"API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
is_active(request)[source]

返回 True 以在 get_post_parameters()get_traceback_frame_variables() 中激活过滤。默认情况下,如果 DEBUGFalse,则过滤器处于活动状态。请注意,敏感的 request.META 值始终与敏感设置值一起过滤,如 DEBUG 文档中所述。

get_post_parameters(request)[source]

返回过滤后的 POST 参数字典。敏感值将替换为 cleansed_substitute

get_traceback_frame_variables(request, tb_frame)[source]

返回给定回溯帧的局部变量的过滤后的字典。敏感值将替换为 cleansed_substitute

如果您需要自定义错误报告以超出过滤的范围,可以通过定义 DEFAULT_EXCEPTION_REPORTER 设置来指定自定义错误报告器类。

DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"

异常报告器负责编译异常报告数据,并将其格式化为文本或 HTML 格式。(异常报告器在准备异常报告数据时使用 DEFAULT_EXCEPTION_REPORTER_FILTER。)

自定义报告器类需要继承自 django.views.debug.ExceptionReporter

class ExceptionReporter[source]
html_template_path[source]

返回一个表示异常 HTML 表示形式的模板的绝对文件系统路径的 pathlib.Path 的属性。默认为 Django 提供的模板。

text_template_path[source]

返回表示异常纯文本表示形式模板的绝对文件系统路径的 pathlib.Path 的属性。默认为 Django 提供的模板。

get_traceback_data()[source]

返回包含回溯信息的字典。

这是自定义异常报告的主要扩展点,例如

from django.views.debug import ExceptionReporter


class CustomExceptionReporter(ExceptionReporter):
    def get_traceback_data(self):
        data = super().get_traceback_data()
        # ... remove/add something here ...
        return data
get_traceback_html()[source]

返回异常报告的 HTML 版本。

用于调试 500 HTTP 错误页面的 HTML 版本。

get_traceback_text()[source]

返回异常报告的纯文本版本。

用于调试 500 HTTP 错误页面的纯文本版本和电子邮件报告。

与过滤器类一样,您可以通过设置 HttpRequestexception_reporter_class 属性来控制在任何给定视图中使用哪个异常报告器类。

def my_view(request):
    if request.user.is_authenticated:
        request.exception_reporter_class = CustomExceptionReporter()
    ...

另请参阅

您还可以通过编写自定义的 异常中间件 来设置自定义错误报告。如果您确实编写了自定义错误处理,最好模仿 Django 的内置错误处理,并且仅在 DEBUGFalse 时报告/记录错误。

返回顶部