В зависимости от задач можно по-разному переопределить в Django стандартное поведение на реакцию ошибок, таких как 403, 404, 500 и стандартные шаблоны вывода ошибок. В официальной документации (на рус. яз. — http://djbook.ru/rel1.8/topics/http/views.html) хорошо это описывается, но тем не менее есть некоторые нюансы, о которых я хочу рассказать и показать в примерах.
В большинстве случаев можно оставить стандартное поведение Django, т. е. стандартные views (из django.views.defaults), обрабатывающие ошибки и переопределить только шаблоны.
Допустим, у нас есть шаблон ошибки 404:
# 404.html
{% extends "base.html" %}
{% block subtitle %}Страница не найдена{% endblock %}
{% block meta %}<meta name="robots" content="noindex, nofollow">{% endblock %}
{% block content %}
<h2>Запрашиваемая страница не найдена</h2>
<p>Возможно, неправильно указан путь в адресной строке или страница была удалена.</p>
<p>Возврат на <a href="/">главную страницу</a></p>
{% endblock %}
А ниже описаны разные способы переопределения.
Добавление своего шаблона в templates
Самый простой способ переопределения — это добавить этот шаблон в «my_project / templates». Именно здесь django будет искать шаблон 404.html и при наличии отрендерит.
Добавление своего шаблона в другую папку
Не всегда удобно держать шаблоны ошибок в «my_project / templates» вместе с какими-то другими шаблонами и хочется их вынести в отдельную папку. Я, к примеру, использую следующую структуру папки templates в корне проекта (жирным выделены папки):
- admin — содержит переопределяемые админские шаблонов
- cms — содержит переопределяемые шаблоны Django CMS
- errs — содержит шаблоны ошибок
- 403.html
- 404.html
- 500.html
- vers — содержит проверочные файлы для поисковых систем
- base.html
- one_col.html
- two_col.html
- main.html
Как видите, вынос шаблонов ошибок в отдельную папку — хорошая идея отделить их от шаблонов страниц (one_col.html, two_col.html, main.html). Чтобы указать django, где искать шаблоны по новому пути, нужно использовать метод curry, например:
# urls.py from django.views.defaults import server_error, page_not_found, permission_denied handler403 = curry(permission_denied, template_name='errs/403.html') handler404 = curry(page_not_found, template_name='errs/404.html') handler500 = curry(server_error, template_name='errs/500.html')
Замечание: в Django>=1.9 нужно добавить ещё один аргумент exception для handler403 и handler404:
handler403 = curry(permission_denied, exception=Exception('Permission Denied'), template_name='errs/403.html')
handler404 = curry(page_not_found, exception=Exception('Page not Found'), template_name='errs/404.html')
Тестирование своих шаблонов ошибок
Чтобы протестировать шаблоны ошибок, достаточно добавить соответствующие urls в urls.py, например так:
if settings.DEBUG:
urlpatterns = [
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
url(r'', include('django.contrib.staticfiles.urls')),
# --- error pages ---
url(r'^403$', handler403),
url(r'^404$', handler404),
url(r'^500$', handler500),
] + urlpatterns
Теперь можно переходить по адресу http://localhost:8000/404 и видеть свой кастомный шаблон ошибки. На боевом сайте нам тестовые урлы ошибок не нужны, поэтому мы добавили их в условие if settings.DEBUG:.
Создание своего представления для обработки ошибки
Если хочется изменить стандартное поведение обработки ошибок, то нужно писать своё представление. Например:
# urls.py
handler403 = 'my_app.views.show_403'
handler404 = 'my_app.views.show_404'
# my_app/views.py
# Обработка ошибки 403
from django.core.exceptions import PermissionDenied
def show_403(request):
# какие-либо действия
raise PermissionDenied
# Обработка ошибки 404
from django.http.response import Http404
def show_404(request):
# какие-либо действия
raise Http404
Можно усложнить пример с обработкой ошибки 404. Например, мы хотим отдавать разные шаблоны 404 в зависимости от того, с чего начинается отсутствующий url:
# Обработка ошибки 404
from django.http.response import Http404
def 404(request):
if request.path.startswith('/project/'):
return render(request, 'project_not_found.html') # выдаст страницу, что проекта нет и, к примеру, покажет другие проекты
if request.path.startswith('/shop/'):
return render(request, 'product_not_found.html') # выдаст страницу, что товара нет и, к примеру, покажет другие товары
raise Http404 # в остальных случаях показать стандартное исключение, которое отрендерит наш шаблон 404.html
Некоторые тонкости
Проверка отдачи шаблона 404
Для проверки отдачи шаблона 404 используйте при значении переменной DEBUG=False в settings.py, иначе вам будет показан трейсбек Django.
Внимание! Если DEBUG=False, то вы должны добавить в ALLOWED_HOSTS (в settings.py) допустимые доменные имена, иначе Django будет выдавать ошибку “Bad Request (400)”. На локальной машине добавляется ‘localhost’ (или 127.0.0.1).
# settings.py ALLOWED_HOSTS = ['localhost', ]
Обратите внимание, что при DEBUG=False статические файлы не будут показываться. Для показа статических файлов нужно собрать статику и запустить сервер с опцией --insecure:
python manage.py collectstatic python manage.py runserver --insecure
Создание своего представления для обработки 500 ошибки
При использовании стандартного представления обработки 500 ошибки в соответствующий шаблон не передаётся контекст. Сделано так для того, чтобы уменьшить количество возможных других ошибок. Поэтому шаблон должен быть простой подобный этому:
<!DOCTYPE html>
<html>
<head>
<title>Ошибка на стороне сервера</title>
<meta name="robots" content="noindex, nofollow">
</head>
<body>
<p>Извините, но что-то случилось с сайтом.</p>
<p>В техническую поддержку уже отправлено уведомление.</p>
</body>
</html>
Если будете делать своё представление для 500 ошибки, то следуйте правилам django — не передавайте RequestContext при рендеринге шаблона. Посмотрите как происходит обработка в стандартном представлении django.views.defaults.server_error.
Отображение ошибок без рендеринга шаблонов
from django.http import HttpResponseNotFound
def test_view_1(request, param):
if not param: # какое-то условие
return HttpResponseNotFound('<p>Страница не найдена</p>')
return render_to_response('test_view_1.html')
from django.http.response import HttpResponseForbidden
def test_view_2(request, param):
if not param:
return HttpResponseForbidden('Доступ запрещён')
return render_to_response('test_view_2.html')
Надеюсь, статья помогла ответить на возникающие вопросы об обработке ошибок в Django.
Оцените статью
3.9 из 5 (всего 7 оценок)
После нажатия кнопки «Отправить» ваше сообщение будет доставлено мне на почту.
Артём Мальцев
Веб-разработчик, владеющий знаниями языка программирования Python, фреймворка Django, системы управления содержимым сайта Django CMS, платформы для создания интернет-магазина Django Shop и многих различных приложений, использующих эти технологии.
Права на использование материала, расположенного на этой странице https://vivazzi.pro/ru/it/django-custom-templates-for-errors/:
Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:
Автор статьи: Артём Мальцев
Ссылка на статью: <a href="https://vivazzi.pro/ru/it/django-custom-templates-for-errors/">https://vivazzi.pro/ru/it/django-custom-templates-for-errors/</a>
Больше: Правила использования сайта
Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.
Книга предназначается для широкого круга читателей и, по мнению автора, будет полезна специалистам отдела закупок и логистики, категорийным и финансовым менеджерам, менеджерам по продажам, аналитикам, руководителям и директорам, в компетенции которых принятие решений по управлению ассортиментом.
(Всего: 19 438, сегодня: 1 )

Выше показан пример стандартной обработки 403-й ошибки браузером, которая означает, что доступ в определенную директорию сайта заблокирован через http-запрос, а 404-я ошибка выглядит еще более скудной.

В большинство CMS встроены варианты перенаправления посетителей в случае отсутствия страниц или запрета доступа к ним. Вот на этом сайте к примеру такой вариант:

Довольно забавно и самое главное — посетитель остается на сайте, не на отдельной, специально разработанной для таких ошибок странице, а именно внутри сайта.
Я когда то заинтересовался данными редиректами и освоил эту систему. у меня был статический сайт на php-каркасе(футер,хэдр). Вот такая же ошибка на моем тестовом сайтике на локальном сервере:

Для 404–й такая же, но по другому правилу редиректа и с другим текстом для 403-й ошибки!
Htaccess
Создать файл .htaccess (точка впереди обязательна и никакого формата. Точка и хтацес)

Открыть блокнотом и написать две строчки:
ErrorDocument 403 http://art.test1.ru/error403.php
ErrorDocument 404 http://art.test1.ru/error404.php
Заменить адрес сайта на свои и адреса страниц также на свои
Страницы ошибок
Далее необходимо подготовить страницы, на которые будет осуществляться перенаправление. Такие страницы ничем не отличаются от остальных на сайте, разве, что, служат для иных целей.
В этой статье мы рассмотри как настроить свой шаблон для страниц ошибок 403, 404, 500 в Django 4.1.
Настройка представлений для ошибок
Первое, что нам необходимо сделать, это создать соответствующие представления для отлова ошибок и рендеринга своих шаблонов.
Делать мы это будем в файле views.py нашего приложения system:
system/views.py
from django.shortcuts import render
def tr_handler404(request, exception):
"""
Обработка ошибки 404
"""
return render(request=request, template_name='system/errors/error_page.html', status=404, context={
'title': 'Страница не найдена: 404',
'error_message': 'К сожалению такая страница была не найдена, или перемещена',
})
def tr_handler500(request):
"""
Обработка ошибки 500
"""
return render(request=request, template_name='system/errors/error_page.html', status=500, context={
'title': 'Ошибка сервера: 500',
'error_message': 'Внутренняя ошибка сайта, вернитесь на главную страницу, отчет об ошибке мы направим администрации сайта',
})
def tr_handler403(request, exception):
"""
Обработка ошибки 403
"""
return render(request=request, template_name='system/errors/error_page.html', status=403, context={
'title': 'Ошибка доступа: 403',
'error_message': 'Доступ к этой странице ограничен',
})
Обработка в urls.py
Далее нам необходимо добавить обработку представлений в главном urls.py файле:
backend/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from django.contrib.sitemaps.views import sitemap
from modules.blog.sitemaps import StaticSitemap, ArticleSitemap
from modules.blog.feeds import LatestArticlesFeed
sitemaps = {
'static': StaticSitemap,
'articles': ArticleSitemap,
}
handler403 = 'modules.system.views.tr_handler403'
handler404 = 'modules.system.views.tr_handler404'
handler500 = 'modules.system.views.tr_handler500'
urlpatterns = [
path('ckeditor5/', include('django_ckeditor_5.urls')),
path('admin/', admin.site.urls),
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
path('feeds/latest/', LatestArticlesFeed(), name='latest_articles_feed'),
path('', include('modules.blog.urls')),
path('', include('modules.system.urls')),
]
if settings.DEBUG:
urlpatterns = [path('__debug__/', include('debug_toolbar.urls'))] + urlpatterns
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Создание шаблона для ошибок
В папке templates/system создадим папку errors, а в ней файл error_page.html со следующим содержимым:
templates/system/errors/error_page.html
{% extends 'main.html' %}
{% block content %}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
{{ error_message }} | <a href="{% url 'home' %}"><strong>Вернуться на главную</strong></a>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endblock content %}
Далее, чтобы увидеть работу наших страниц с ошибками, нам необходимо поставить режим DEBUG = False (т.е отключить).
Проверка работы страницы с ошибкой
Аналогично будет работать со страницей 403, 500. Только сообщение об ошибке будет то, что мы указали в представлении.
- 1. Кастомизация ошибок 404, 500
- 2. Кастомизация ошибки 403
Многие ресурсы имеют оформленные страницы ошибок, если происходит сбой в обработке запроса от клиента.
Для начала на сайте была сделана кастомизация наиболее часто возникающих ошибок, другие при отладке пока не попадались, но всё впереди.
Как объявлено в заголовке статьи, кастомизированы был следующие ошибки:
- 403 — Ошибка авторизации, доступ запрещён.
- 404 — Страница не найдена;
- 500 — Внутренняя ошибка сервера;
Кастомизация ошибок 404, 500
Для кастомизации ошибок 404 и 500 необходимо написать обработчики запросов, и достаточно написать их представления в виде метода.
В шаблоны добавляем свои кастомизированные html файлы, то есть:
- error404.html
- error500.html
Модуль, в котором реализованы представления для данного сайта — это
home.
В шаблонах этого же модуля помещены сами шаблоны кастомизированных ошибок.
В файле
urls.py
главного модуля сайта переопределяем обработчики по умолчанию:
- handler404
- handler500
В коде это выглядит так:
from home.views import e_handler404, e_handler500 handler404 = e_handler404 handler500 = e_handler500Опишем представления в файле
views.py
модуля
home:
from django.shortcuts import render_to_response from django.template import RequestContext def e_handler404(request): context = RequestContext(request) response = render_to_response('error404.html', context) response.status_code = 404 return response def e_handler500(request): context = RequestContext(request) response = render_to_response('error500.html', context) response.status_code = 500 return responseКастомизация ошибки 403
Ошибка 403 возникает в том случае, когда не авторизованный пользователь пытается получить доступ к той части сайта, в которую доступ разрешён только авторизованным пользователям.
В Django это достигается за счёт проверки статуса пользователя и добавления на страницы защитного токена, механизм
CSRF.
Данная ошибка может возникнуть и в том случае, если пользователь авторизован, но совершает действия, при которых требуется проверка токена CSRF, а сам токен был потерян или не верен. Дело в том, что для корректности работы токена, необходимо добавлять в шаблоне в формах специальный тег:{% csrf_token %}В него и будет подставляться токен, но просто добавить в шаблон, его не достаточно. Прежде, чем начать рендер шаблон, необходимо добавить токен в контекст, который будет передан в шаблон. То есть,
from django.template.context_processors import csrf from django.shortcuts import render_to_response def any_request(request): context = {} context.update(csrf(request)) ... return render_to_response('any_request.html', context=context)Ну а теперь ближе к непосредственно кастомизации. Для работы csrf необходимо, чтобы в файле
settings.py
добавлен модуль csrf и указано представление, которое будет заниматься обработкой данной ошибки:MIDDLEWARE = [ ... 'django.middleware.csrf.CsrfViewMiddleware', ... ] CSRF_FAILURE_VIEW = 'home.views.csrf_failure'В шаблонах добавим
error403.html,
а в файле
views.py
пропишем обработчик представления.def csrf_failure(request, reason=""): context = RequestContext(request) response = render_to_response('error403.html', context) response.status_code = 403 return responseДля
Django
рекомендуюVDS-сервера хостера Timeweb
.
5
19
Все уже наверно сталкивались с ситуацией, когда при посещении какого-либо сайта выскакивает надпись
Forbidden You don’t have permission to access on this server и нужный сайт не загружается.
Данная ситуация возможна в том случае, если Вы пытаетесь обратиться к ресурсам сайта, доступ к которым запрещен,
либо Ваш IP адрес был забанен на данном сайте. В данном случае код ответа сервера будет равен 403. Проще говоря, сервер возвращает
ошибку 403 (или страничку 403).
В данной теме мы предлагаем Вам создать свою собственную страничку 403 для отслеживания активности заблокированных
IP адресов и IP адресов, пытающихся обратиться к ресурсам, доступ к которым закрыт.
Своя собственная страничка 403 может быть полезна для тех, кто хочет знать, прекратились ли обращения к
страницам сайта с забаненных IP адресов или нет, и кто пытается получить доступ к файлам с ограниченным доступом.
Для начала, давайте посмотрим, как выглядит исходный код странички, которая появляется при попытке доступа к
файлу .htaacces:
HTML код:
<!DOCTYPE html>
<html lang="en"><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /.htaacces
on this server.</p>
</body></html>
Для создания своей собственной странички 403, создайте файл (например, error403.php). Внутрь данного файла поместите выше
приведенный HTML код с сообщением, после которого добавьте PHP код, который будет писать логи:
PHP код:
<?php
if (filesize("logs_403.txt")<99999) {
$fh=fopen("logs_403.txt","a+");
flock($fh,LOCK_EX);
fseek($fh,0);
while (!feof($fh)) $str.=fread($fh,8192);
$str.=date("H:i:s d m Y")." | ".htmlspecialchars($_SERVER['REMOTE_ADDR']." | ".
$_SERVER['HTTP_USER_AGENT']." | ".$_SERVER['REQUEST_URI']."rn");
ftruncate($fh,0);
fwrite($fh,$str);
flock($fh,LOCK_UN);
fclose($fh);
}
?>
Для того чтобы страничка 403 стала универсальной и выдавала в сообщение URL, к которому закрыт доступ,
в HTML коде замените строчку <p>You don’t have permission to access /.htaacces на
<p>You don’t have permission to access /<?php echo strtok(basename($_SERVER[‘REQUEST_URI’]), ‘?’).’ ‘;?>
Теперь Вам остается лишь перенаправить посетителя со стандартной странички 403 на Вашу собственную.
Для этого в файле .htaccess добавьте всего одну строчку:
Цитата:
ErrorDocument 403 /error403.php
Все. Теперь все IP адреса, доступ которым запрещен на сайт и IP адреса, которые пытаются получить доступ к защищенным
ресурсам сайта, будут попадать в файл логов logs_403.txt с указанием времени, User_Agent-а и URL, по которому они пытались получить доступ.
Обращаем Ваше внимание на то, что мы специально добавили в PHP код дополнительное условие проверки
if (filesize(«logs_403.txt»)<99999) для того, чтобы при быстром росте размера файла логов и превышении им
размера в 99999 байт, логи в файл перестали записываться для снижения нагрузки на сервер.
При всем при этом стоит учитывать, что предлагаемая нами собственная страничка 403 при очень частом
обращении к ней повысит нагрузку на сервер, так что смотрите сами, стоит ли Вам создавать свою собственную страничку ошибки
403 если сервер у Вас слабый.
Дата создания: 16:12:47 13.06.2013 г.
Посещений: 7907 раз(а).
Перед публикацией все комментарии проходят обязательную модерацию!
Если Вы хотите задать какой-либо вопрос, то сделайте это на нашем форуме.
Таким образом, Вы сможете быстрее получить ответ на интересующий Вас вопрос.



