Свои шаблоны для обработки ошибок 403, 404 в django

10 февраля 2016 г. 5:53

В зависимости от задач можно по-разному переопределить в 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_HOSTSsettings.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 оценок)

captcha
Отмеченные звёздочкой поля ( * ) являются обязательными для заполнения.

Спасибо за ваш отзыв!

После нажатия кнопки "Отправить" ваше сообщение будет доставлено мне на почту.

Автор статьи

Артём Мальцев

Веб-разработчик, владеющий знаниями языка программирования 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>

Больше: Правила использования сайта

Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.

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

Комментарии: 0

Вы можете оставить комментарий как незарегистрированный пользователь.

Но зарегистрировавшись, вы сможете:

  • получать оповещения об ответах
  • просматривать свои комментарии
  • иметь возможность использовать все функции разработанных сервисов

Для комментирования от своего имени войдите или зарегистрируйтесь на сайте Vuspace

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте

Выберите валюту для отображения денежных единиц