Django, criando uma página de erro 500/404 personalizada


105

Seguindo exatamente o tutorial encontrado aqui , não consigo criar uma página de erro 500 ou 404 personalizada. Se eu digitar um url incorreto, a página me mostra a página de erro padrão. Há algo que eu deveria verificar para evitar que uma página personalizada seja exibida?

Diretórios de arquivos:

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

em mysite / settings.py eu habilitei estes:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

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

em 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'),
)

Posso postar qualquer outro código necessário, mas o que devo mudar para obter uma página de erro 500 personalizada se usar um URL incorreto?

Editar

SOLUÇÃO: eu tinha um adicional

TEMPLATE_DIRS

em meu settings.py e isso estava causando o problema


1
Debug está definido como False em meu código
Zac


1
Encontrei esta resposta enquanto procurava uma maneira de fazer apenas um template customizado e queria compartilhar um pouco da documentação do Django que me ajudou muito; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52

O meu funcionou sem a configuração template_dirs.
Programmingjoe

1
Pontos para ironia quando o link na primeira linha leva à página 404 do Django. Leva a uma página de tutorial para uma versão do Django que não existe, eu acho. Aqui está o link para a página do tutorial do Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Respostas:


120

Em seu principal, views.pyadicione sua própria implementação personalizada das duas visualizações a seguir e apenas configure os modelos 404.html e 500.html com o que deseja exibir.

Com esta solução, nenhum código personalizado precisa ser adicionado ao urls.py

Aqui está o código:

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

Atualizar

handler404e handler500são exportadas variáveis ​​de configuração de string Django encontradas emdjango/conf/urls/__init__.py . É por isso que a configuração acima funciona.

Para fazer com que a configuração acima funcione, você deve definir as seguintes variáveis ​​em seu urls.pyarquivo e apontar as variáveis ​​exportadas do Django para o caminho do Python da string de onde essas visualizações funcionais do Django são definidas, como:

# project/urls.py

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

Atualização para Django 2.0

As assinaturas para visualizações do manipulador foram alteradas no Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Se você usar visualizações como acima, o handler404 falhará com a mensagem:

"handler404 () obteve um argumento de palavra-chave inesperado 'exceção'"

Nesse caso, modifique suas opiniões da seguinte forma:

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

Isso pareceu funcionar muito bem para mim, mas por algum motivo request.user aparece bem no modelo 404, mas não no modelo 500 (e eles são quase idênticos) - poste uma pergunta sobre isso aqui: stackoverflow.com/ perguntas / 26043211 /…
Sepultura Gravitacional

1
Outra coisa que eu estava pensando - e se você usar o back-end do administrador e quiser usar modelos separados para eles? Que eu saiba, o administrador não tem um views.py para substituir e colocar esse trecho de código.
Gravity Grave

11
@GravityGrave o 500 templatenão renderiza request.userporque está relatando um erro de servidor 500, então o servidor não é capaz de servir nada.
Aaron Lelevier

5
Não funcionou para mim com django 1.9; (Talvez eu esteja fazendo algo errado. Handler404 django é um nome reservado? Como django saberia que deveria chamar exatamente essa visão?
deathangel908

1
Eu atualizei a resposta com base em seu comentário. Desculpe que a atualização esteja tão atrasada. Eu espero que isso ajude.
Aaron Lelevier

71

Resposta oficial:

Aqui está o link para a documentação oficial sobre como configurar visualizações de erro personalizadas:

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

Diz para adicionar linhas como essas em seu URLconf (configurá-las em qualquer outro lugar não terá efeito):

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'

Você também pode personalizar a visualização do erro CSRF, modificando a configuração CSRF_FAILURE_VIEW.

Manipuladores de erro padrão:

Vale a pena ler a documentação dos manipuladores de erro padrão, page_not_found, server_error, permission_deniede bad_request. Por padrão, eles usam esses modelos se eles podem encontrá-los, respectivamente: 404.html, 500.html, 403.html, e 400.html.

Então, se tudo o que você quer fazer é criar belas páginas de erro, basta criar esses arquivos em um TEMPLATE_DIRS diretório, você não precisa editar o URLConf de forma alguma. Leia a documentação para ver quais variáveis ​​de contexto estão disponíveis.

No Django 1.10 e posterior, a visualização de erro CSRF padrão usa o modelo 403_csrf.html.

Peguei vocês:

Não se esqueça de que DEBUGdeve ser definido como False para que funcionem, caso contrário, os manipuladores de depuração normais serão usados.


1
Eu adicionei, mas não funciona. Adicionado o handler404 e outros apontando para os lugares certos em minhas visualizações, mas não funciona, ainda vendo o padrão 404. E sim, estou no modo Debug False e usando 1.9
KhoPhi

Usar Django 1.9 e simplesmente adicionar 500.html templates etc mostra-os ao invés de páginas padrão. Boa solução fácil.
curtisp

2
Gotcha me ajudou. Funcionou fazendo essas alterações em meu settings.py, defina DEBUG = False e ALLOWED_HOSTS = ['0.0.0.0'] para aceitar a solicitação de http de qualquer cliente.
shaffooo

1
Caso alguém esteja se perguntando onde está o URLconf, aqui está
Arthur Tarasov

38

Adicione essas linhas em 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'

# ...

e implementar nossas visualizações personalizadas em 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
Por que você importaria handler400apenas para sobrescrever handler400 = 'myapp.views.bad_request'?
Flimm


5
Você não precisa importar os manipuladores aqui para substituí-los.
funkotron

1
Você não deve usar render_to_response. Dos documentos: "não é recomendado e provavelmente será descontinuado no futuro."
Timmy O'Mahony,

Para Django 1.10, como render_to_responsevai ser descontinuado, consulte o seguinte (use em rendervez disso): stackoverflow.com/questions/44228397/…
mrdaliri

21

Na página que você referiu:

Quando você cria o Http404 de dentro de uma visão, o Django carrega uma visão especial dedicada a lidar com erros 404. Ele o encontra procurando pela variável handler404 em seu URLconf root (e apenas em seu URLconf root; definir handler404 em qualquer outro lugar não terá efeito), que é uma string na sintaxe com pontos do Python - o mesmo formato que os callbacks URLconf normais usam. Uma visão 404 em si não tem nada de especial: é apenas uma visão normal.

Portanto, acredito que você precisa adicionar algo assim ao seu urls.py:

handler404 = 'views.my_404_view'

e semelhante para handler500.


Como isso parece Mike? Hoje é meu primeiro dia usando Django e ainda estou me segurando nas cordas
Zac

2
@JimRilye Você precisará adicionar uma função 500 adequada às suas visualizações e, em seguida, referenciá-la com essa variável. Portanto, acima de sua urlpatterns = ...linha, adicione uma linha que diga handler500 = 'views.handle500'e, em seguida, adicione um def handle500(request):ao seu views.py que exibe seu 500.html.
Mike Pelley

18

Se tudo o que você precisa é mostrar páginas personalizadas que têm algumas mensagens de erro sofisticadas para o seu site quando DEBUG = False, então adicione dois modelos chamados 404.html e 500.html no seu diretório de modelos e ele irá selecionar automaticamente essas páginas personalizadas quando um 404 ou 500 é gerado.


1
Isso funciona, apenas certifique-se de ter algo como: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]em sua lista de TEMPLATES no settings.py.
Eric,

12

No Django 2. * você pode usar esta construção em views.py

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

Em settings.py

DEBUG = False

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

if DEBUG is True:
    ALLOWED_HOSTS = []

Em urls.py

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

Normalmente eu crio default_app e lido com erros de todo o site, processadores de contexto nele.


Trabalhe para mim. Mas o que é exception?
zeleven

De acordo com o link de documentação: docs.djangoproject.com/en/2.1/ref/urls/… . Está escrito: certifique-se de que o gerenciador aceita os argumentos de solicitação e exceção
Alouani Younes

1
Trabalhou para mim no Django 3.0 . Mas o que é locals()? O arquivo só mostra pass.
enchance

9

settings.py:

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

e apenas adicione suas páginas 404.htmle 500.htmlna pasta de modelos. remover 404.htmle 500.htmlde modelos no aplicativo de enquetes.


Como usar a mensagem de raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} também está disponível.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


7

Cometa um erro, na página de erro, descubra de onde django está carregando os modelos. Quero dizer, a pilha de caminhos. No template_dir base, adicione essas páginas html 500.html , 404.html . Quando esses erros ocorrerem, os respectivos arquivos de modelo serão carregados automaticamente.

Você também pode adicionar páginas para outros códigos de erro, como 400 e 403 .

Espero esta ajuda !!!


6

No Django 3.x, a resposta aceita não funcionará porque render_to_responsefoi removida completamente, assim como mais algumas mudanças foram feitas desde a versão para a qual a resposta aceita funcionou.

Algumas outras respostas também estão lá, mas estou apresentando uma resposta um pouco mais clara:

Em seu urls.pyarquivo principal :

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

No yourapp/views.pyarquivo:

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

Certifique-se de ter importado render()no yourapp/views.pyarquivo:

from django.shortcuts import render

Nota lateral: render_to_response()foi descontinuado no Django 2.xe foi completamente removido na versão 3.x.


5

Como uma única linha (para a página 404 genérica):

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
E onde usar?
Sami

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' 

Isso funciona no django 2.0

Certifique-se de incluir seu personalizado 404.htmldentro da pasta de modelos de aplicativos.


4

Django 3.0

aqui está o link para personalizar visualizações de erros

aqui está o link como renderizar uma visualização

no urls.py(o principal, na pasta do projeto), coloque:

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'

e nesse aplicativo ( my_app_name) coloque 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", {})

NOTA: error/404.htmlé o caminho se você colocar seus arquivos na pasta de modelos de projetos (não nos aplicativos), templates/errors/404.htmlportanto, coloque os arquivos onde quiser e escreva o caminho correto.

NOTA 2: Depois de recarregar a página, se você ainda vir o modelo antigo, altere-o settings.py DEBUG=True, salve-o e depois novamente em False(para reiniciar o servidor e coletar os novos arquivos).


Observação extra: se você estiver executando em DEUB=Falseseus arquivos estáticos, pode não ser veiculado, fazendo com que você não possa visualizar as alterações do modelo de erro personalizado. Use ./manage.py runserver --insecurepara forçar o Django a servi-los de qualquer maneira.
Rob


3

Tente mover seus modelos de erro para .../Django/mysite/templates/?

Tenho certeza sobre este, mas acho que eles precisam ser "globais" para o site.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.