- 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
.
Режим отладки проекта
Сейчас ваш проект работает в режиме отладки: при установке проекта в конфиге был автоматически выставлен флаг DEBUG=True
. В этом режиме при ошибках выводится страница с технической информацией и подробным разбором строк, в которых что-то пошло не так.
Пользователям такие страницы показывать нельзя. Во-первых, это некрасиво, непонятно и бессмысленно: пользователю не нужна эта информация, исследование причин ошибок не входит в задачи посетителей. Во-вторых, это небезопасно: в отладочной информации могут содержаться ключи доступа к внешним сервисам или к базе данных.
При публикации сайта на боевом сервере режим разработки нужно отключать. Тогда при ошибках вместо отладочных страниц будут отображаться просто страницы с сообщениями об ошибке.
Страницы ошибок
Чтобы отключить режим отладки (его ещё называют «режим разработки» или «режим разработчика»), в settings.py нужно установить значение DEBUG=False
. После этого страницы с ошибками вы увидите в совершенно ином виде.
В Django есть предустановленные страницы ошибок (например, для ошибки 404 — «страница не найдена» или для 403 — «запрос отклонён»); однако выглядят эти страницы так, будто разработчику сайта не было до них дела. Нельзя оставлять их в таком виде: пользователи будут неприятно изумлены.
Создадим собственные страницы ошибок; они относятся ко всему проекту, поэтому будет логично описать их view-функции и шаблоны в приложении core
.
Ошибка 404: страница не найдена
Подготовим view-функцию для страницы 404:
# core/views.py
from django.shortcuts import render
def page_not_found(request, exception):
# Переменная exception содержит отладочную информацию;
# выводить её в шаблон пользовательской страницы 404 мы не станем
return render(request, 'core/404.html', {'path': request.path}, status=404)
Шаблон этой страницы будет таким:
# templates/core/404.html
{% extends "base.html" %}
{% block title %}Custom 404{% endblock %}
{% block content %}
<h1>Custom 404</h1>
<p>Страницы с адресом {{ path }} не существует</p>
<a href="{% url 'home:index' %}"> Идите на главную</a>
{% endblock %}
Django распознаёт ошибки и вызывает для их обработки заготовленные view-функции. Имена этих функций хранятся в специальных переменных — хендлерах (англ. handlers). Адрес view-функции с ошибкой 404 хранится в переменной handler404
(по умолчанию это view-функция django.views.defaults.page_not_found
).
Хендлер можно переопределить: передать в него имя собственной view-функции. Для этого достаточно добавить в головной url-файл проекта такую строчку:
# urls.py
handler404 = 'core.views.page_not_found'
В результате при ошибке 404 отработает view-функция page_not_found()
и отобразится кастомная страница ошибки. А уж настроить эту страницу — дело фронтендера.
Разумеется, дизайн может быть каким угодно.
Обработка прочих ошибок выполняется точно так же. В Django заготовлены переменные handler400
, handler403
и несколько других, в документации есть их перечень.
403: ошибка проверки CSRF, запрос отклонён
Ошибка 403 в Django появится в том случае, если при отправке формы не был отправлен csrf-токен. Страница этой ошибки кастомизируется немного иначе: view-функция и шаблон готовятся, как и для других страниц, но переопределяется не хандлер, а константа CSRF_FAILURE_VIEW
в settings.py.
View-функция:
# core/views.py
from django.shortcuts import render
def csrf_failure(request, reason=''):
return render(request, 'core/403csrf.html')
Шаблон:
# templates/core/403csrf.html
{% extends "base.html" %}
{% block content %}
<h1>Custom CSRF check error. 403</h1>
{% endblock %}
Имя view-функции, обрабатывающей ошибку 403, указывается в settings.py, в константе CSRF_FAILURE_VIEW
:
PYTHON# settings.py
CSRF_FAILURE_VIEW = 'core.views.csrf_failure'
Включение и отключение режима отладки
При разработке реальных проектов вы будете публиковать их на сервере, при этом нужно будет отключать режим отладки. Для этого в файле settings.py нужно установить значение ключа DEBUG=False
.
После отключения режима разработки у вас перестанет показываться статика. Это нормально: в «боевом режиме» Django ожидает, что статику будет раздавать специально настроенный сервер.
После отключения режима разработки может возникнуть и другая проблема: при обращении к страницам сайта может вернуться ошибка 400: Bad Request. Эта ошибка может возникнуть как на локальном компьютере, так и на удалённом сервере.
Причина — в settings.py в списке ALLOWED_HOSTS
не указан адрес вашего сервера.
Проверьте этот список, в нём должны быть указаны адреса, на которых может быть размещён проект:
DEBUG = False
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'[::1]',
'testserver',
]
После проверки работы шаблонов не забудьте вернуть сайт в режим разработки:
DEBUG = True
Я пытаюсь автоматизировать тестирование 404 страниц с помощью платформы тестирования Django 1.4.
если я распечатаю 127.0.0.1:8000/something/really/weird/
в адресной строке браузера с запущенным сервером разработки я вижу страницу 404 с правильным статусом «404 не найден» (как показывает firebug).
но если я пытаюсь использовать этот код для проверки:
from django.test import TestCase
class Sample404TestCase(TestCase):
def test_wrong_uri_returns_404(self):
response = self.client.get('something/really/weird/')
self.assertEqual(response.status_code, 404)
тест терпит неудачу с этим выходом:
$./manage.py test main
Creating test database for alias 'default'...
.F
======================================================================
FAIL: test_wrong_uri_returns_404 (main.tests.Sample404TestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".../main/tests.py", line 12, in test_wrong_uri_returns_404
self.assertEqual(response.status_code, 404)
*AssertionError: 200 != 404*
----------------------------------------------------------------------
Ran 2 tests in 0.031s
FAILED (failures=1)
Destroying test database for alias 'default'...
Я серьезно удивлен, получив 200 код здесь. Кто-нибудь знает, почему на земле это происходит?
обновление:
здесь лежит urls.py:http://pastebin.com/DikAVa8T
и фактический неудачный тест:
def test_wrong_uri_returns_404(self):
response = self.client.get('/something/really/weird/')
self.assertEqual(response.status_code, 404)
все происходит в проекте https://github.com/gbezyuk/django-app-skeleton
2 ответов
проблема в том, что ваш класс ViewFor404 возвращает код состояния 200. Посмотрите на определение TemplateView Джанго:
class TemplateView(TemplateResponseMixin, View):
"""
A view that renders a template.
"""
def get_context_data(self, **kwargs):
return {
'params': kwargs
}
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
Так что все ваши класса является render_to_response, который генерирует ‘200’ ответ.
Если вам нужно переопределить обработчик 404, вы должны сделать что-то вроде этого в представлении:
return HttpResponseNotFound('<h1>Page not found</h1>')
(Я не знаю эквивалента в представлениях на основе классов)
или еще лучше, вы можете избежать настройки посмотреть? К настроить отображение 404, вы можете просто создать 404.html-шаблон (в шаблонах/ каталоге вашего сайта), и он будет подхвачен средством просмотра ошибок Django.
попробовать
response = self.client.get('/something/really/weird/') # note the '/' before something
127.0.0.1:8000/something/really/weird/
is /something/really/weird/
в пути относительно корня,не
something/really/weird
something/really/weird/
/something/really/weird
10 июля, 2015 12:54 пп
1 573 views
| Комментариев нет
Centos, Cloud Server, VPS
Apache – самый популярный в мире веб-сервер; многофункциональный и гибкий, он постоянно развивается и поддерживается командой высококвалифицированных специалистов.
При проектировании веб-страниц часто возникает необходимость настроить каждую страницу индивидуально. Это касается и страниц ошибок, которые появляются, если запрашиваемый контент по какой-либо причине недоступен. В этом руководстве показано, как настроить Apache для отображения пользовательских страниц ошибок в системе CentOS 7.
Требования
Для выполнения данного руководства нужна уётная запись пользователя с привилегиями sudo. Чтобы настроить такого пользователя, обратитесь к этому руководству. Кроме того, нужно предварительно установить Apache; подробные инструкции по установке веб-сервера можно получить здесь.
Создание пользовательской страницы ошибок
Для начала создайте пользовательские страницы ошибок.
Примечание: Для тестирования можно использовать следующий код без изменений. Чтобы создать свою страницу ошибок, просто замените текст в echo в приведённом ниже коде.
Страницы ошибок будут находиться в каталоге /var/www/html – стандартном каталоге document root веб-сервера Apache. Для примера создайте страницу ошибки 404 (по имени custom_404.html) и общую страницу для ошибок 500 (назовите её custom_50x.html).
echo "<h1 style='color:red'>Error 404: Not found :-(</h1>" | sudo tee /var/www/html/custom_404.html
echo "<p>I have no idea where that file is, sorry. Are you sure you typed in the correct URL?</p>" | sudo tee -a /var/www/html/custom_404.html
echo "<h1>Oops! Something went wrong...</h1>" | sudo tee /var/www/html/custom_50x.html
echo "<p>We seem to be having some technical difficulties. Hang tight.</p>" | sudo tee -a /var/www/html/custom_50x.html
Итак, теперь на сервере есть две страницы ошибок.
Настройка Apache для отображения пользовательских страниц ошибок
Теперь нужно настроить Apache для поддержки только что созданных страниц в случае возникновения соответствующей ошибки. Создайте новый конфигурационный файл в каталоге /etc/httpd/conf.d, который хранит настройки для Apache. Назовите файл custom_errors.conf:
sudo nano /etc/httpd/conf.d/custom_errors.conf
Направьте Apache на соответствующие страницы ошибок.
Для того чтобы связать каждый тип ошибки со специальной страницей ошибок, используйте директиву ErrorDocument. В целом, нужно просто указать код состояния HTTP для каждой страницы, и тогда страница появится на экране в случае возникновения указанной ошибки.
В данном случае настройки будут выглядеть так:
/etc/httpd/conf.d/custom_errors.conf
ErrorDocument 404 /custom_404.html
ErrorDocument 500 /custom_50x.html
ErrorDocument 502 /custom_50x.html
ErrorDocument 503 /custom_50x.html
ErrorDocument 504 /custom_50x.html
Этих настроек достаточно, чтобы обслуживать пользовательские страницы ошибок.
Однако рекомендуется добавить ещё один блок конфигураций, чтобы клиенты не могли запрашивать страницы ошибок напрямую. Это предотвратит путаницу (например, запрошенная напрямую страница ошибки будет сообщать пользователю об ошибке, даже если код состояния – 200 (Success)).
Чтобы настроить такое поведение веб-сервера, нужно добавить блок Files для каждой пользовательской страницы ошибок. Также нужно проверить, установлена ли переменная окружения REDIRECT_STATUS; она должна быть установлена только если директива ErrorDocument обрабатывает запрос. Если переменная окружения пуста, сервер будет обслуживать страницу 404:
/etc/httpd/conf.d/custom_errors.conf
ErrorDocument 404 /custom_404.html
ErrorDocument 500 /custom_50x.html
ErrorDocument 502 /custom_50x.html
ErrorDocument 503 /custom_50x.html
ErrorDocument 504 /custom_50x.html
<Files "custom_404.html">
<If "-z %{ENV:REDIRECT_STATUS}">
RedirectMatch 404 ^/custom_404.html$
</If>
</Files>
<Files "custom_50x.html">
<If "-z %{ENV:REDIRECT_STATUS}">
RedirectMatch 404 ^/custom_50x.html$
</If>
</Files>
Когда страницы ошибок запрашиваются клиентами, возникает ошибка 404, потому что переменная среды не установлена.
Тестирование страницы ошибок 500
Проверить работу страницы ошибок 404 очень просто: нужно запросить любой несуществующий контент. Чтобы протестировать страниц ошибок 500, нужно создать фиктивный ProxyPass.
Добавьте директиву ProxyPass в конец конфигурационного файла. Отправьте запросы для /proxytest на порт 9000 на локальной машине (на этом порте не запущено ни одного сервиса):
/etc/httpd/conf.d/custom_errors.conf
ErrorDocument 404 /custom_404.html
ErrorDocument 500 /custom_50x.html
ErrorDocument 502 /custom_50x.html
ErrorDocument 503 /custom_50x.html
ErrorDocument 504 /custom_50x.html
<Files "custom_404.html">
<If "-z %{ENV:REDIRECT_STATUS}">
RedirectMatch 404 ^/custom_404.html$
</If>
</Files>
<Files "custom_50x.html">
<If "-z %{ENV:REDIRECT_STATUS}">
RedirectMatch 404 ^/custom_50x.html$
</If>
</Files>
ProxyPass /proxytest "http://localhost:9000"
Сохраните и закройте файл.
Тестирование страниц ошибок
Проверьте конфигурационный файл на наличие ошибок:
sudo apachectl configtest
Если команда обнаружила любые ошибки, исправьте их. После этого перезапустите Apache:
sudo systemctl restart httpd
Откройте домен или IP-адрес сервера и запросите несуществующий контент, чтобы проверить работу страницы 404:
http://server_domain_or_IP/thiswillerror
На экране должна появиться страница 404:
Error 404: Not found :-(
I have no idea where that file is, sorry. Are you sure you typed in the correct URL?
Откройте фиктивный proxypass, чтобы проверить работу страницы 500 (на экране должен появиться код состояния 503 service unavailable):
http://server_domain_or_IP/proxytest
Если всё настроено верно, на экране появится:
Oops! Something went wrong...
We seem to be having some technical difficulties. Hang tight.
После тестирования удалите фиктивную директиву из конфигураций Apache.
Заключение
Итак, теперь на сайте есть уникальные страницы ошибок. Пользовательские страницы ошибок – это отличный способ помочь посетителям понять, в чём дело, предоставить им всю необходимую информацию об ошибке и полезные ссылки (не забудьте убедиться, что ссылки работают даже в случае возникновения ошибок).
Tags: Apache, CentOS 7