Как управлять сообщениями об ошибках
При работе с общедоступным сайтом всегда следует отключать параметр DEBUG. Это значительно ускорит работу сервера, а также не позволит злоумышленникам увидеть сведения о вашем приложении, которые могут раскрыть страницы ошибок.
Однако при значении False для DEBUG вы никогда не увидите ошибки, возникающие на сайте: вместо этого всем будут показываться общедоступные страницы ошибок. Необходимо отслеживать ошибки, возникающие на развернутых сайтах, поэтому 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 и в запросе указан реферер. Письма об ошибках 404 без реферера не отправляются: обычно такие ошибки возникают, когда пользователи вводят неверные URL или когда их запрашивают неисправные веб-боты. Django также игнорирует ошибки 404, если реферер совпадает с запрошенным 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 и его атрибуты.
Однако иногда определенные типы информации могут быть слишком конфиденциальными, чтобы сохранять их, например пароль пользователя или номер кредитной карты. Помимо фильтрации настроек, которые могут содержать конфиденциальные сведения, как описано в документации по 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)[исходный код] -
Если одно из ваших представлений получает объект
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"], ) ...В приведенном выше примере значения POST-параметров
pass_wordиcredit_card_numberбудут скрыты и заменены звездочками (**********) в представлении запроса в отчетах об ошибках, а значение параметра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"
Можно также более гибко выбирать фильтр для конкретного представления, задав атрибут exception_reporter_filter объекта HttpRequest:
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_filter = CustomExceptionReporterFilter()
...
Ваш пользовательский класс фильтра должен наследоваться от django.views.debug.SafeExceptionReporterFilter и может переопределять следующие атрибуты и методы:
-
class SafeExceptionReporterFilter[исходный код] -
-
cleansed_substitute -
Строковое значение, которым заменяются конфиденциальные данные. По умолчанию значения конфиденциальных переменных заменяются звездочками (
**********).
-
Скомпилированный объект регулярного выражения, используемый для поиска настроек и значений
request.META, которые считаются конфиденциальными. По умолчанию эквивалентен:import re re.compile(r"API|AUTH|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
Изменено в Django 5.2:Добавлен термин
AUTH.
-
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 и отчетов по электронной почте.
-
Как и в случае с классом фильтра, можно выбрать класс формирования отчетов об исключениях для конкретного представления, задав атрибут exception_reporter_class объекта HttpRequest:
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/6.0/howto/error-reporting/