如何管理错误报告¶
在运行公共站点时,您应该始终关闭 DEBUG
设置。这将使您的服务器运行速度更快,并且还可以防止恶意用户查看应用程序的详细信息,这些详细信息可能会在错误页面中泄露。
但是,将 DEBUG
设置为 False
意味着您将永远看不到站点生成的错误 - 每个人都将看到您的公共错误页面。您需要跟踪部署站点中发生的错误,以便可以将 Django 配置为创建包含有关这些错误的详细信息的报告。
电子邮件报告¶
服务器错误¶
当 DEBUG
为 False
时,只要您的代码引发未处理的异常并导致内部服务器错误(严格来说,对于任何 HTTP 状态代码为 500 或更大的响应),Django 都会向 ADMINS
设置中列出的用户发送电子邮件。这使管理员可以立即收到任何错误的通知。 ADMINS
将收到错误的描述、完整的 Python 回溯以及导致错误的 HTTP 请求的详细信息。
注意
为了发送电子邮件,Django 需要一些设置来告诉它如何连接到您的邮件服务器。至少,您需要指定 EMAIL_HOST
,并且可能还需要指定 EMAIL_HOST_USER
和 EMAIL_HOST_PASSWORD
,尽管根据邮件服务器的配置,可能还需要其他设置。请参阅 Django 设置文档 以获取电子邮件相关设置的完整列表。
默认情况下,Django 将从 root@localhost 发送电子邮件。但是,一些邮件提供商会拒绝来自此地址的所有电子邮件。要使用不同的发件人地址,请修改 SERVER_EMAIL
设置。
要激活此行为,请将收件人的电子邮件地址放在 ADMINS
设置中。
另请参阅
服务器错误电子邮件是使用日志记录框架发送的,因此您可以通过 自定义日志记录配置 来自定义此行为。
404 错误¶
Django 还可以配置为发送有关损坏链接(404“页面未找到”错误)的错误电子邮件。当以下条件满足时,Django 会发送有关 404 错误的电子邮件:
DEBUG
为False
;您的
MIDDLEWARE
设置包括django.middleware.common.BrokenLinkEmailsMiddleware
。
如果满足这些条件,则只要您的代码引发 404 并且请求具有引用者,Django 就会向 MANAGERS
设置中列出的用户发送电子邮件。对于没有引用者的 404,它不会发送电子邮件 - 这些通常是用户输入错误的 URL 或错误的 Web 机器人。当引用者等于请求的 URL 时,它也会忽略 404,因为此行为也来自错误的 Web 机器人。
注意
BrokenLinkEmailsMiddleware
必须出现在拦截 404 错误的其他中间件之前,例如 LocaleMiddleware
或 FlatpageFallbackMiddleware
。将其放在 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 ...
在上面的示例中,
user
、pw
和cc
变量的值将在错误报告中隐藏并替换为星号 (**********
),而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_word
和credit_card_number
POST 参数的值将在错误报告中请求的表示形式中隐藏并替换为星号 (**********
),而name
参数的值将被公开。要系统地隐藏错误报告中请求的所有 POST 参数,请不要向
sensitive_post_parameters
装饰器提供任何参数。@sensitive_post_parameters() def my_view(request): ...
对于某些
django.contrib.auth.views
视图(login
、password_reset_confirm
、password_change
以及auth
管理中的add_view
和user_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"
您还可以通过设置 HttpRequest
的 exception_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¶
用于替换敏感值的字符串值。默认情况下,它用星号 (
**********
) 替换敏感变量的值。
用于匹配被视为敏感的设置和
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()
中激活过滤。默认情况下,如果DEBUG
为False
,则过滤器处于活动状态。请注意,敏感的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 提供的模板。
与过滤器类一样,您可以通过设置 HttpRequest
的 exception_reporter_class
属性来控制在任何给定视图中使用哪个异常报告器类。
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_class = CustomExceptionReporter()
...