# Django 5.2.8 documentation

# 如何管理错误报告

当您运行着公开的网页时，你应该把设置中的 `DEBUG` 选项设为关闭。 这将使您的服务器运行得更快，并且还可以防止恶意用户在错误页面中看到应用的详细信息。

然而，把配置 `DEBUG` 设置为 `False`， 这意味着你永远不会在你的网站上看到错误的细节，所有的人相应会看到你公开的错误页面。当你需要在部署的网页上追踪出现的错误，Django 可以通过设置去报告错误的细节。

## 通过邮件方式报告

### 服务器错误

当 `DEBUG` 为 `False` 时，Django 会在代码抛出的异常未被捕获且导致一个内部的服务器错误（HTTP 状态码 500）时向 `ADMINS` 配置中列出的用户发送邮件。这让管理员立刻收到错误通知。 `ADMINS` 列表中的用户，会收到详细的错误描述，完整的 Python 调用栈，和引发此错误的 HTTP 请求的细节。

Note

要发送邮件，Django 要求一些配置项，告诉它如何连接至邮件服务器。最小配置下，你需要指定 `EMAIL_HOST` 和 `EMAIL_HOST_USER` 和 `EMAIL_HOST_PASSWORD`，可能还有其它配置，这取决于邮件服务器的配置。查阅 Django 配置文档 获取邮件相关配置的完整列表。

By default, Django will send email from `root@localhost`. However, some mail providers reject all email from this address. To use a different sender address, modify the `SERVER_EMAIL` setting.

要启动该行为，将收件人的邮箱地址放入 `ADMINS`。

See also

服务器错误邮件由 logging 框架发出，所以你能通过 自定义 logging 配置 自定义该行为。

### 404 错误

Django 也能配置成为已失效的连接发送错误邮件（404 "page not found" 错误）。Django 发送 404 错误邮件的条件：

- `DEBUG` 为 `False`；

- `MIDDLEWARE` 配置包括 `django.middleware.common.BrokenLinkEmailsMiddleware`。

如果满足这些条件，Django 会在你的代码出现 404 并且请求有引用来源时，给 `MANAGERS` 配置中列出的用户发送电子邮件。对于没有引用来源的 404，Django 懒得发邮件——那些通常是人们输入了错误的 URL 或错误的网络机器人。当引用来源等于被请求的 URL 时，它也会忽略 404，因为这种行为也是来自坏掉的网络机器人。

Note

`BrokenLinkEmailsMiddleware` 必须出现在其他拦截 404 错误的中间件之前，例如 `LocaleMiddleware` 或者 `FlatpageFallbackMiddleware`。把它放在你的 `MIDDLEWARE` 配置的顶部。

你可以通过调整配置项 `IGNORABLE_404_URLS` 让 Django 忽略某些 404s。内容应该是已编译的正则表达式的列表。例子:

    import re

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

在本例中，对以 `.php` 或 `.cgi` 结尾的 URL 的 404 错误将 不会 被报告。以 `phpmyadmin` 开头的也不会被报告。

下面的例子展示了如何排除一些浏览器和爬虫经常访问的传统 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` 的行为（例如忽略来自网络爬虫的请求），你需要继承该类，并重写方法。

See also

404 错误由 logging 框架报告。默认情况下，这些日志记录被忽略了，但你能通过编写一个处理器和 配置 logging 让它们报告错误。

## 过滤错误报告

Warning

过滤敏感数据是一个很难的问题，几乎不可能保证敏感数据不会泄漏到错误报告中。因此，错误报告应该只提供给受信任的团队成员，你应该避免在互联网上传输未加密的错误报告（如通过电子邮件）。

### 过滤敏感数据

错误报告对于调试错误来说超级有用，所以通常尽可能多的记录关键信息。例如，Django 默认记录了抛出异常的 完整调用栈，每个 调用栈层 的局部变量，以及 `HttpRequest` 的 属性。

然而，有时候某些信息会涉及敏感内容，因此不适合写入调用栈。例如，用户的密码或信用卡号。故此，为了过滤 `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
          ...

  上述例子中，错误报告中变量 `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): ...

sensitive_post_parameters(*parameters)

  若视图收到一个包含 `POST 参数` 的 `HttpRequest` 对象，参数中极有可能内含敏感信息。你可以通过 `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"],
          )
          ...

  上文例子中，POST 参数 `pass_word` 和 `credit_card_number` 的值会被隐藏，通过在错误报告中展示请求信息的地方用星号开头的字符串 (`**********`)替换，而参数 `name` 的值不会被屏蔽。

  要在错误报告中系统的屏蔽所有 POST 参数，不要给 `sensitive_post_parameters` 装饰器提供任何参数:

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

  为了避免敏感信息的泄露（例如账号密码）， 所有传入认证视图 `django.contrib.auth.views` （`login`， `password_reset_confirm`， `password_change`， and `add_view` 和 `auth` 后台中的 `user_change_password`）的 POST 参数都在错误报告中经过系统过滤。

### 自定义错误报告

`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
  cleansed_substitute

    用于替换敏感值的字符串。默认情况下，它将敏感参数的值替换成星号 (**********)。

  hidden_settings

    一个编译了的用于匹配配置和 `request.META` 值的不忽略大写的正则表达式对象。默认相当于

        import re

        re.compile(r"API|AUTH|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)

    Changed in Django 5.2:

    The term `AUTH` was added.

  is_active(request)

    返回 `True` 以在 `get_post_parameters()` 和 `get_traceback_frame_variables()` 中激活过滤。默认情况下如果配置 `DEBUG` 为 `False` 则过滤器会启动。请注意，就像文档中配置 `DEBUG` 描述的一样，敏感的 `request.META` 请求值总是会以配置好的值过滤掉。

  get_post_parameters(request)

    返回POST参数过滤后的字典。敏感参数的值会被替换成 `cleansed_substitute`。

  get_traceback_frame_variables(request, tb_frame)

    返回给定的调用栈层中的局部变量经过过滤后的字段。敏感值会被替换成 `cleansed_substitute`。

如果你需要在过滤器之外自定义错误报告，你可以指定一个自定义写在配置 `DEFAULT_EXCEPTION_REPORTER` setting:: 配置的错误报告类

    DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"

异常报告工具负责编译异常报告并将其整理成文本或HTML文件的形式。（当准备要报告的异常数据的时候异常报告工具使用配置 `DEFAULT_EXCEPTION_REPORTER_FILTER` ）

你的自定义的报告类需要继承自类 :class: django.views.debug.ExceptionReporter 。

class ExceptionReporter
  html_template_path

    返回一个 `pathlib.Path` 的类，该路径表示模板的绝对文件系统路径，用于呈现异常的 HTML 表示。 默认为 Django 提供的模板。

  text_template_path

    返回一个 `pathlib.Path` 的类，该路径表示模板的绝对文件系统路径，用于呈现异常的纯文本表示。 默认为 Django 提供的模板。

  get_traceback_data()

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

    这是自定义异常报告工具的主要扩展点，如下:

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

    返回异常报告的HTML版本。

    用于返回HTTP 500错误页面的HTML版本。

  get_traceback_text()

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

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

和过滤类一样，你也能在任意视图内通过配置 `HttpRequest` 的 `exception_reporter_filter` 属性来控制具体使用哪个错误报告类:

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

See also

你也能够通过自定义一系列的 异常中间层 定制错误报告行为。若你已经编写了自定义错误处理器，模仿 Django 内置的错误处理器，并只在 `DEBUG` 为 `False` 时报告或记录错误是个不错的主意。