Spec-Zone.ru › Django 4.2

Как управлять обработкой ошибок

При работе с общедоступным сайтом всегда следует выключать настройку DEBUG. Это значительно ускорит работу сервера и предотвратит доступ злоумышленников к деталям вашего приложения, которые могут быть раскрыты страницами ошибок.

Однако, работа с настройкой DEBUG, установленной в False, означает, что вы никогда не увидите ошибки, генерируемые вашим сайтом — все увидят общедоступные страницы ошибок. Вам необходимо отслеживать ошибки, возникающие на развернутых сайтах, поэтому Django можно настроить для создания отчетов с деталями этих ошибок.

Отчёты по электронной почте

Ошибки сервера

Когда DEBUG имеет значение False, Django будет отправлять электронные письма пользователям, указанным в настройке ADMINS, всякий раз, когда ваш код вызывает необработанное исключение, приводящее к внутренней ошибке сервера (строго говоря, для любого ответа с кодом состояния HTTP 500 или выше). Это обеспечивает администраторам немедленное уведомление о любых ошибках. В 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.

Если эти условия выполнены, Django будет отправлять электронные письма пользователям, указанным в настройке MANAGERS, всякий раз, когда ваш код вызывает ошибку 404, и у запроса есть поле referer. Django не отправляет письма для ошибок 404, у которых нет referer — обычно это люди, вводящие некорректные URL-адреса или роботы. Также игнорируются ошибки 404, когда referer равен запрошенному URL, так как это также поведение некорректных веб-ботов.

Примечание

BrokenLinkEmailsMiddleware должен располагаться перед другими обработчиками, которые перехватывают ошибки 404, такими как LocaleMiddleware или FlatpageFallbackMiddleware. Поместите его в начало настройки MIDDLEWARE.

Вы можете указать Django, чтобы он не сообщал о конкретных ошибках 404, настроив настройку IGNORABLE_404_URLS. Она должна быть списком скомпилированных объектов регулярных выражений. Например:

import re

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

В этом примере ошибка 404 для любого URL, заканчивающегося на .php или .cgi, не будет сообщена. Точно так же не будет сообщаться о любом URL, начинающемся с /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 (например, чтобы игнорировать запросы от веб-ботов), вы можете создать его подкласс и переопределить его методы.

См. также

Ошибки 404 записываются в журнал с помощью фреймворка логирования. По умолчанию эти записи журнала игнорируются, но вы можете использовать их для отчета об ошибках, создав обработчик и правильно настроив логирование.

Фильтрация отчетов об ошибках

Предупреждение

Фильтрация конфиденциальных данных — сложная задача, и практически невозможно гарантировать, что конфиденциальные данные не попадут в отчет об ошибке. Поэтому отчеты об ошибках должны быть доступны только проверенным членам команды, и вы должны избегать передачи отчетов об ошибках без шифрования по сети Интернет (например, по электронной почте).

Фильтрация конфиденциальной информации

Отчеты об ошибках очень полезны для отладки ошибок, поэтому обычно полезно записывать как можно больше релевантной информации об этих ошибках. Например, по умолчанию Django записывает полную трассировку для поднятого исключения, локальные переменные каждой рамки трассировки и HttpRequest’s атрибуты.

Однако, иногда определённые типы информации могут быть слишком конфиденциальными и не должны храниться, например, пароль пользователя или номер кредитной карты. Поэтому, помимо фильтрации настроек, которые кажутся конфиденциальными, как описано в документации 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):
    ...

Предупреждение

Из-за механизмов, необходимых для перехода между синхронной и асинхронной областями, sync_to_async() и async_to_sync() несовместимы с sensitive_variables().

Если вы используете эти адаптеры с конфиденциальными переменными, убедитесь в проверке отчетов об ошибках и рассмотрите возможность реализации пользовательского фильтра, если это необходимо.

sensitive_post_parameters(*parameters)

Если один из ваших представлений получает объект 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):
    ...

Все параметры POST систематически отфильтровываются из отчётов об ошибках для определенных представлений django.contrib.auth.views (login, password_reset_confirm, password_change, и add_view и user_change_password в админке auth), чтобы предотвратить утечку конфиденциальной информации, такой как пароли пользователей.

Настраиваемые отчёты об ошибках

Все sensitive_variables() и sensitive_post_parameters() делают следующее: соответственно, аннотируют декорированную функцию именами конфиденциальных переменных и аннотируют объект HttpRequest именами конфиденциальных параметров POST, чтобы эта конфиденциальная информация могла быть впоследствии отфильтрована из отчётов при возникновении ошибки. Фактический фильтр выполняется стандартным фильтром отчёта об ошибках Django: django.views.debug.SafeExceptionReporterFilter. Этот фильтр использует аннотации декораторов для замены соответствующих значений звёздочками (**********) при формировании отчётов об ошибках. Если вы хотите переопределить или настроить это поведение по всему сайту, вам необходимо определить свой собственный класс фильтра и указать Django использовать его через настройку DEFAULT_EXCEPTION_REPORTER_FILTER:

DEFAULT_EXCEPTION_REPORTER_FILTER = "path.to.your.CustomExceptionReporterFilter"

Вы также можете более точно управлять тем, какой фильтр использовать в конкретном представлении, задав атрибут HttpRequest’s 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|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
Изменено в Django 4.2:

HTTP_COOKIE был добавлен.

is_active(request)

Возвращает True для активации фильтрации в get_post_parameters() и get_traceback_frame_variables(). По умолчанию фильтр активен, если DEBUG имеет значение False. Обратите внимание, что конфиденциальные значения request.META всегда отфильтровываются вместе с конфиденциальными значениями настроек, как описано в документации к DEBUG.

get_post_parameters(request)

Возвращает отфильтрованный словарь параметров POST. Конфиденциальные значения заменяются на cleansed_substitute.

get_traceback_frame_variables(request, tb_frame)

Возвращает отфильтрованный словарь локальных переменных для указанной рамки отслеживания ошибок. Конфиденциальные значения заменяются на cleansed_substitute.

Если вам нужно настроить отчёты об ошибках более подробно, чем просто фильтрация, вы можете указать пользовательский класс отчётчика об ошибках, определив настройку DEFAULT_EXCEPTION_REPORTER:

DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"

Отчётчик об ошибках отвечает за компиляцию данных об ошибках и соответствующую форматирование как текста, так и HTML. (Отчётчик об ошибках использует DEFAULT_EXCEPTION_REPORTER_FILTER при подготовке данных об ошибках.)

Ваш пользовательский класс отчётчика должен наследоваться от 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-версию отчёта об ошибках.

Используется для HTML-версии страницы ошибки HTTP 500.

get_traceback_text()

Возвращает текстовую версию отчёта об ошибках.

Используется для текстовой версии страницы ошибки HTTP 500 и отчётов по электронной почте.

Как и с классом фильтра, вы можете управлять тем, какой класс отчётчика об ошибках использовать в конкретном представлении, задав атрибут HttpRequest’s exception_reporter_class:

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

См. также

Вы также можете настроить отчёт об ошибках, написав пользовательский фрагмент обработчика исключений. Если вы пишете пользовательскую обработку ошибок, рекомендуется эмулировать встроенную обработку ошибок Django и сообщать/логировать ошибки только если DEBUG имеет значение False.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.2/howto/error-reporting/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API