Как управлять отчётами об ошибках
При работе с публичным сайтом всегда следует выключить настройку 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, и запрос имеет referrer. Он не беспокоится об отправке электронных писем для ошибок 404, у которых нет referrer — это обычно люди, вводящие неверные URL-адреса или неисправные веб-боты. Он также игнорирует ошибки 404, когда referrer равен запрошенному URL-адресу, так как это поведение также свойственно неисправным веб-ботам.
Примечание
BrokenLinkEmailsMiddleware должен стоять перед другим middleware, который перехватывает ошибки 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)[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_numberPOST будут скрыты и заменены звёздочками (**********) в представлении запроса внутри отчетов об ошибках, в то время как значение параметра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) для предотвращения утечки конфиденциальной информации, такой как пароли пользователей.Изменено в Django 5.0:Была добавлена поддержка обертывания функций
async.
Настраиваемые отчёты об ошибках
Все 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 в 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] -
Свойство, которое возвращает
pathlib.Path, представляющий абсолютный путь к файловой системе шаблона для рендеринга HTML представления ошибки. По умолчанию используется шаблон, предоставляемый 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 версию отчета об ошибке.
Используется для HTML версии страницы ошибки HTTP 500.
-
get_traceback_text()[source] -
Возвращает текстовую версию отчета об ошибке.
Используется для текстовой версии страницы ошибки HTTP 500 и отчетов по электронной почте.
-
Как и с классом фильтра, вы можете управлять тем, какой класс отчёта об ошибках использовать в любом заданном представлении, установив атрибут HttpRequest в 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/5.1/howto/error-reporting/