Django, создание настраиваемой страницы ошибок 500/404


106

В точности следуя приведенному здесь руководству , я не могу создать собственную страницу ошибок 500 или 404. Если я введу неправильный URL-адрес, на странице появится страница с ошибкой по умолчанию. Есть ли что-нибудь, что я должен проверить, чтобы предотвратить отображение настраиваемой страницы?

Каталоги файлов:

mysite/
    mysite/
        __init__.py
        __init__.pyc
        settings.py
        settings.pyc
        urls.py
        urls.pyc
        wsgi.py
        wsgi.pyc
    polls/
        templates/
            admin/
                base_site.html
            404.html
            500.html
            polls/
                detail.html
                index.html
        __init__.py
        __init__.pyc
        admin.py
        admin.pyc
        models.py
        models.pyc
        tests.py
        urls.py
        urls.pyc
        view.py
        views.pyc
    templates/
    manage.py

в mysite / settings.py я включил:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

TEMPLATE_DIRS = (
    'C:/Users/Me/Django/mysite/templates', 
)

в mysite / polls / urls.py:

from django.conf.urls import patterns, url

from polls import views

urlpatterns = patterns('',
    url(r'^$', views.index, name='index'),
    url(r'^(?P<poll_id>\d+)/$', views.detail, name='detail'),
    url(r'^(?P<poll_id>\d+)/results/$', views.results, name='results'),
    url(r'^(?P<poll_id>\d+)/vote/$', views.vote, name='vote'),
)

Я могу опубликовать любой другой необходимый код, но что мне следует изменить, чтобы получить настраиваемую страницу с ошибкой 500, если я использую неправильный URL-адрес?

редактировать

РЕШЕНИЕ: у меня был дополнительный

TEMPLATE_DIRS

в моем settings.py, и это вызывало проблему


1
В моем коде для отладки установлено значение False
Zac

Это может помочь вам stackoverflow.com/a/12180499/1628832
karthikr

1
Нашел этот ответ, когда искал способ создать только собственный шаблон, и я хотел поделиться небольшой документацией по Django, которая мне очень помогла; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52,

Моя работала без настройки template_dirs.
Programmingjoe

1
Очки за иронию, когда ссылка в первой строке ведет на страницу 404 Django. Переходит на страницу руководства по несуществующей версии Django. Вот ссылка на страницу руководства по Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Ответы:


121

Под основным views.pyдобавьте свою собственную реализацию следующих двух представлений и просто настройте шаблоны 404.html и 500.html с тем, что вы хотите отобразить.

С помощью этого решения не нужно добавлять специальный код в urls.py

Вот код:

from django.shortcuts import render_to_response
from django.template import RequestContext


def handler404(request, *args, **argv):
    response = render_to_response('404.html', {},
                                  context_instance=RequestContext(request))
    response.status_code = 404
    return response


def handler500(request, *args, **argv):
    response = render_to_response('500.html', {},
                                  context_instance=RequestContext(request))
    response.status_code = 500
    return response

Обновить

handler404и handler500экспортируются строковые конфигурационные переменные Django, найденные в django/conf/urls/__init__.py. Вот почему приведенная выше конфигурация работает.

Чтобы вышеуказанная конфигурация работала, вы должны определить следующие переменные в своем urls.pyфайле и указать экспортированные переменные Django на строковый путь Python, в котором определены эти функциональные представления Django, например:

# project/urls.py

handler404 = 'my_app.views.handler404'
handler500 = 'my_app.views.handler500'

Обновление для Django 2.0

Подписи для представлений обработчиков были изменены в Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Если вы используете представления, как указано выше, handler404 выдаст сообщение:

"handler404 () получил неожиданный аргумент ключевого слова 'исключение'"

В таком случае измените свои представления следующим образом:

def handler404(request, exception, template_name="404.html"):
    response = render_to_response(template_name)
    response.status_code = 404
    return response

Мне показалось, что это работает довольно хорошо, но по какой-то причине request.user выглядит нормально в шаблоне 404, но совсем не в шаблоне 500 (и они почти идентичны) - разместил вопрос по этому поводу здесь: stackoverflow.com/ вопросы / 26043211 /…
Gravity Grave

1
Еще одна вещь, о которой мне было интересно, - что, если вы используете бэкэнд администратора и хотите использовать для них отдельные шаблоны? Насколько мне известно, у администратора нет views.py, чтобы переопределить и вставить этот фрагмент кода.
Gravity Grave

11
@GravityGrave 500 templateне будет отображаться, request.userпотому что он сообщает об ошибке сервера 500, поэтому сервер не может что-либо обслуживать.
Аарон Лелевье

5
У меня не получилось с django 1.9; (Возможно, я что-то делаю не так. Зарезервировано ли имя handler404 django? Как django узнает, что он должен вызывать именно это представление?
deathangel908

1
Я обновил ответ на основе вашего комментария. Извините, что обновление так поздно. Я надеюсь, что это помогает.
Аарон Лелевье

71

Официальный ответ:

Вот ссылка на официальную документацию о том, как настроить пользовательские просмотры ошибок:

https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views

Он говорит, что нужно добавить такие строки в ваш URLconf (установка их в другом месте не будет иметь никакого эффекта):

handler404 = 'mysite.views.my_custom_page_not_found_view'
handler500 = 'mysite.views.my_custom_error_view'
handler403 = 'mysite.views.my_custom_permission_denied_view'
handler400 = 'mysite.views.my_custom_bad_request_view'

Вы также можете настроить представление ошибок CSRF, изменив настройку CSRF_FAILURE_VIEW.

Обработчики ошибок по умолчанию:

Это стоит прочитать документацию обработчиков ошибок по умолчанию, page_not_found, server_error, permission_deniedи bad_request. По умолчанию, они используют эти шаблоны , если они могут их найти, соответственно: 404.html, 500.html, 403.html, и 400.html.

Так что, если все, что вам нужно, это сделать красивые страницы с ошибками, просто создайте эти файлы в TEMPLATE_DIRSкаталоге, вам вообще не нужно редактировать URLConf. Прочтите документацию, чтобы узнать, какие контекстные переменные доступны.

В Django 1.10 и более поздних версиях представление ошибок CSRF по умолчанию использует шаблон 403_csrf.html.

Попался:

Не забывайте, что для этого DEBUGдолжно быть установлено значение False, иначе будут использоваться обычные обработчики отладки.


1
Я добавил, но не работает. Добавлен handler404 и другие, указывающие на правильные места в моих представлениях, но он не работает, по-прежнему отображается значение по умолчанию 404. И да, я нахожусь в режиме Debug False и использую 1.9
KhoPhi

Использование Django 1.9 и простое добавление шаблонов 500.html и т. Д. Показывает их вместо стандартных страниц. Хорошее простое исправление.
curtisp

2
Попался мне помог. Он работал, внося эти изменения в мой settings.py, устанавливая DEBUG = False и ALLOWED_HOSTS = ['0.0.0.0'], чтобы принимать HTTP-запрос от любого клиента.
shaffooo

1
На всякий случай, если кому-то еще интересно, где вообще находится URLconf, вот он
Артур Тарасов

@ArthurTarasov Да, лучше было бы сослаться на файл urls.py вместе с ним, ха-ха.
Зак Плауше,

40

Добавьте эти строки в urls.py

urls.py

from django.conf.urls import (
handler400, handler403, handler404, handler500
)

handler400 = 'my_app.views.bad_request'
handler403 = 'my_app.views.permission_denied'
handler404 = 'my_app.views.page_not_found'
handler500 = 'my_app.views.server_error'

# ...

и реализуем наши пользовательские представления в views.py.

views.py

from django.shortcuts import (
render_to_response
)
from django.template import RequestContext

# HTTP Error 400
def bad_request(request):
    response = render_to_response(
        '400.html',
        context_instance=RequestContext(request)
        )

        response.status_code = 400

        return response

# ...

5
Зачем вам импортировать handler400только для перезаписи handler400 = 'myapp.views.bad_request'?
Flimm


5
Вам не нужно импортировать здесь обработчики, чтобы переопределить их.
funkotron

1
Вы не должны использовать render_to_response. Из документации: «это не рекомендуется и, скорее всего, в будущем будет прекращено».
Тимми О'Махони

Для Django 1.10, render_to_responseкоторый будет считаться устаревшим, см. Следующее (используйте renderвместо него): stackoverflow.com/questions/44228397/…
mrdaliri

21

Со страницы, на которую вы ссылались:

Когда вы вызываете Http404 из представления, Django загружает специальное представление, посвященное обработке ошибок 404. Он находит его, ища переменную handler404 в вашем корневом URLconf (и только в корневом URLconf; установка handler404 в любом другом месте не будет иметь никакого эффекта), которая представляет собой строку в синтаксисе Python с точками - тот же формат, что и обычные обратные вызовы URLconf. Само представление 404 не имеет ничего особенного: это просто нормальное представление.

Поэтому я считаю, что вам нужно добавить что-то вроде этого в свой urls.py:

handler404 = 'views.my_404_view'

и аналогично для handler500.


Как это выглядит, Майк? Сегодня я впервые использую Django, и я все еще держусь за веревки
Зак

2
@JimRilye Вам нужно добавить подходящую функцию 500 в свои представления, а затем ссылаться на нее с помощью этой переменной. Итак, над вашей urlpatterns = ...строкой добавьте строку с надписью handler500 = 'views.handle500', а затем добавьте def handle500(request):в свой views.py, который отображает ваш 500.html.
Майк Пелли

18

Если все, что вам нужно, это показать пользовательские страницы, на которых есть какие-то необычные сообщения об ошибках для вашего сайта DEBUG = False, тогда добавьте два шаблона с именами 404.html и 500.html в свой каталог шаблонов, и он автоматически подберет эти пользовательские страницы при 404 или 500 Поднялся.


1
Это работает, просто убедитесь, что у вас есть что-то вроде: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]в вашем списке ШАБЛОНЫ в settings.py.
eric

12

В Django 2. * вы можете использовать эту конструкцию в views.py

def handler404(request, exception):
    return render(request, 'errors/404.html', locals())

В settings.py

DEBUG = False

if DEBUG is False:
    ALLOWED_HOSTS = [
        '127.0.0.1:8000',
        '*',
    ]

if DEBUG is True:
    ALLOWED_HOSTS = []

В urls.py

# https://docs.djangoproject.com/en/2.0/topics/http/views/#customizing-error-views
handler404 = 'YOUR_APP_NAME.views.handler404'

Обычно я создаю default_app и обрабатываю в нем ошибки на уровне сайта, обработчики контекста.


Работай на меня. Но что это exception?
zeleven

Согласно ссылке на документацию: docs.djangoproject.com/en/2.1/ref/urls/… . Написано: убедитесь, что обработчик принимает аргументы запроса и исключения
Алуани Юнес

1
У меня работал в Django 3.0 . Но что есть locals()? Файл только показывает pass.
Enchance

9

settings.py:

DEBUG = False
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['localhost']  #provide your host name

и просто добавить свои 404.htmlи 500.htmlстраницы в папке шаблонов. удалить 404.htmlи 500.htmlиз шаблонов в приложении для опросов.


Как использовать сообщение raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} также доступно.
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功


7

Сделайте ошибку, на странице ошибки узнайте, откуда django загружает шаблоны. Я имею в виду стек путей. В базу template_dir добавьте эти html страницы 500.html , 404.html . Когда возникают эти ошибки, автоматически загружаются соответствующие файлы шаблонов.

Вы также можете добавить страницы для других кодов ошибок, например 400 и 403 .

Надеюсь на эту помощь !!!


6

В Django 3.xпринятый ответ не будет работать, потому что render_to_responseон был полностью удален, а также были внесены некоторые другие изменения с версии, для которой работал принятый ответ.

Есть и другие ответы, но я представляю более чистый ответ:

В вашем основном urls.pyфайле:

handler404 = 'yourapp.views.handler404'
handler500 = 'yourapp.views.handler500'

В yourapp/views.pyфайле:

def handler404(request, exception):
    context = {}
    response = render(request, "pages/errors/404.html", context=context)
    response.status_code = 404
    return response


def handler500(request):
    context = {}
    response = render(request, "pages/errors/500.html", context=context)
    response.status_code = 500
    return response

Убедитесь, что вы импортировали render()в yourapp/views.pyфайл:

from django.shortcuts import render

Боковое примечание: render_to_response()устарело в Django 2.xи полностью удалено в версии 3.x.


5

Одной строкой (для общей страницы 404):

from django.shortcuts import render_to_response
from django.template import RequestContext

return render_to_response('error/404.html', {'exception': ex},
                                      context_instance=RequestContext(request), status=404)

1
А где его использовать?
Сами

5

Дополнительного просмотра не требуется. https://docs.djangoproject.com/en/3.0/ref/views/

Просто поместите файлы ошибок в корень каталога шаблонов

  • 404.html
  • 400.html
  • 403.html
  • 500.html

И он должен использовать вашу страницу с ошибкой, когда отладка имеет значение False


4
# views.py
def handler404(request, exception):
    context = RequestContext(request)
    err_code = 404
    response = render_to_response('404.html', {"code":err_code}, context)
    response.status_code = 404
    return response

# <project_folder>.urls.py
handler404 = 'todo.views.handler404' 

Это работает на django 2.0

Не забудьте добавить свой заказ 404.htmlв папку шаблонов приложений.


4

Django 3.0

вот ссылка, как настроить просмотры ошибок

вот ссылка, как визуализировать представление

в urls.py(основной, в папке проекта) положить:

handler404 = 'my_app_name.views.custom_page_not_found_view'
handler500 = 'my_app_name.views.custom_error_view'
handler403 = 'my_app_name.views.custom_permission_denied_view'
handler400 = 'my_app_name.views.custom_bad_request_view'

и в этом приложении ( my_app_name) введите views.py:

def custom_page_not_found_view(request, exception):
    return render(request, "errors/404.html", {})

def custom_error_view(request, exception=None):
    return render(request, "errors/500.html", {})

def custom_permission_denied_view(request, exception=None):
    return render(request, "errors/403.html", {})

def custom_bad_request_view(request, exception=None):
    return render(request, "errors/400.html", {})

ПРИМЕЧАНИЕ: error/404.htmlэто путь, если вы помещаете свои файлы в папку шаблонов проектов (а не приложений), templates/errors/404.htmlпоэтому, пожалуйста, поместите файлы в нужное место и укажите правильный путь.

ПРИМЕЧАНИЕ 2: После перезагрузки страницы, если вы все еще видите старый шаблон, измените его settings.py DEBUG=True, сохраните его, а затем снова False(чтобы перезапустить сервер и собрать новые файлы).


Дополнительное примечание: если вы работаете, DEUB=Falseваши статические файлы могут не обслуживаться, поэтому вы не можете предварительно просмотреть изменения пользовательского шаблона ошибок. Используйте, ./manage.py runserver --insecureчтобы заставить django все равно обслуживать их.
Роб

3

Попробуйте переместить шаблоны ошибок в папку .../Django/mysite/templates/?

Я уверен в этом, но я думаю, что они должны быть «глобальными» для веб-сайта.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.