Django, creando una pagina di errore 500/404 personalizzata


105

Seguendo esattamente il tutorial trovato qui , non riesco a creare una pagina di errore 500 o 404 personalizzata. Se digito un URL errato, la pagina mi dà la pagina di errore predefinita. C'è qualcosa che dovrei controllare per impedire la visualizzazione di una pagina personalizzata?

Directory dei file:

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

all'interno di miosito / settings.py ho questi abilitati:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

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

all'interno di 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 pubblicare qualsiasi altro codice necessario, ma cosa devo cambiare per ottenere una pagina di errore 500 personalizzata se uso un URL non valido?

modificare

SOLUZIONE: ne avevo uno aggiuntivo

TEMPLATE_DIRS

all'interno del mio settings.py e questo stava causando il problema


1
Il debug è impostato su False nel mio codice
Zac

Questo potrebbe aiutare a stackoverflow.com/a/12180499/1628832
karthikr

1
Ho trovato questa risposta mentre cercavo il modo di creare solo un template personalizzato e volevo condividere un po 'di documentazione Django che mi ha aiutato molto; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52

Il mio ha funzionato senza l'impostazione template_dirs.
Programmingjoe

1
Punti per ironia quando il collegamento in prima riga porta alla pagina 404 di Django. Porta a una pagina di tutorial per una versione di Django che non esiste credo. Ecco il link alla pagina del tutorial per Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Risposte:


120

Sotto il tuo main views.pyaggiungi la tua implementazione personalizzata delle seguenti due visualizzazioni e imposta i modelli 404.html e 500.html con ciò che desideri visualizzare.

Con questa soluzione, non è necessario aggiungere codice personalizzato a urls.py

Ecco il codice:

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

Aggiornare

handler404e handler500vengono esportate le variabili di configurazione della stringa Django trovate in django/conf/urls/__init__.py. Ecco perché la configurazione di cui sopra funziona.

Per far funzionare la configurazione di cui sopra, dovresti definire le seguenti variabili nel tuo urls.pyfile e puntare le variabili Django esportate alla stringa Python path in cui sono definite queste viste funzionali Django, in questo modo:

# project/urls.py

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

Aggiornamento per Django 2.0

Le firme per le visualizzazioni del gestore sono state modificate in Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Se usi le viste come sopra, handler404 fallirà con il messaggio:

"handler404 () ha ricevuto un argomento parola chiave imprevisto" eccezione ""

In tal caso, modifica le tue visualizzazioni in questo modo:

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

Questo sembrava funzionare abbastanza bene per me, ma per qualche motivo request.user sembra a posto nel modello 404, ma per niente nel modello 500 (e sono quasi identici) - domanda pubblicata su questo qui: stackoverflow.com/ domande / 26043211 /…
Gravity Grave

1
Un'altra cosa su cui mi chiedevo: cosa succede se usi il backend dell'amministratore e vuoi usare modelli separati per quelli? Per quanto ne so, l'amministratore non ha un views.py per sovrascrivere e inserire questo bit di codice.
Gravity Grave,

11
@GravityGrave 500 templatenon esegue il rendering request.userperché segnala un errore del server 500, quindi il server non è in grado di fornire nulla.
Aaron Lelevier

5
Non ha funzionato per me con django 1.9; (Forse sto facendo qualcosa di sbagliato. Il nome di handler404 django è riservato? Come potrebbe django sapere che dovrebbe chiamare esattamente quella vista?
deathangel908

1
Ho aggiornato la risposta in base al tuo commento. Mi dispiace che l'aggiornamento sia così tardi. Spero che questo aiuti.
Aaron Lelevier

71

Risposta ufficiale:

Ecco il collegamento alla documentazione ufficiale su come impostare le visualizzazioni personalizzate degli errori:

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

Dice di aggiungere righe come queste nel tuo URLconf (impostarle altrove non avrà effetto):

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'

È inoltre possibile personalizzare la visualizzazione degli errori CSRF modificando l'impostazione CSRF_FAILURE_VIEW.

Gestori di errori predefiniti:

Ne vale la pena di leggere la documentazione dei gestori di errori di default, page_not_found, server_error, permission_deniede bad_request. Per impostazione predefinita, usano questi modelli se riescono a trovare, rispettivamente 404.html, 500.html, 403.htmle 400.html.

Quindi, se tutto ciò che vuoi fare è creare belle pagine di errore, crea semplicemente quei file in una TEMPLATE_DIRSdirectory, non hai bisogno di modificare URLConf affatto. Leggi la documentazione per vedere quali variabili di contesto sono disponibili.

In Django 1.10 e versioni successive, la visualizzazione degli errori CSRF predefinita utilizza il modello 403_csrf.html.

Gotcha:

Non dimenticare che DEBUGdeve essere impostato su False affinché funzionino, altrimenti verranno utilizzati i normali gestori di debug.


1
Ho aggiunto, ma non funziona. Aggiunto il gestore 404 e altri che puntano ai punti giusti nelle mie visualizzazioni, ma non funziona, vedendo ancora il 404 predefinito. E sì, sono in modalità Debug False e utilizzo 1.9
KhoPhi

Usando Django 1.9 e aggiungendo semplicemente 500.html ecc template vengono mostrati invece delle pagine standard. Bella soluzione facile.
curtisp

2
Gotcha mi ha aiutato. Ha funzionato apportando queste modifiche nel mio settings.py, impostando DEBUG = False e ALLOWED_HOSTS = ['0.0.0.0'] per accettare la richiesta http da qualsiasi client.
shaffooo

1
Nel caso in cui qualcun altro si stia chiedendo dove diavolo sia URLconf, eccolo qui
Arthur Tarasov

38

Aggiungi queste righe in 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 implementa le nostre visualizzazioni personalizzate in 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
Perché dovresti importare handler400solo per sovrascriverlo handler400 = 'myapp.views.bad_request'?
Flimm


5
Non è necessario importare qui i gestori per sovrascriverli.
funkotron

1
Non dovresti usare render_to_response. Dai documenti: "non è consigliato ed è probabile che venga ritirato in futuro".
Timmy O'Mahony

Per Django 1.10, come render_to_responsesta per essere deprecata, vedere la seguente (uso renderinvece): stackoverflow.com/questions/44228397/...
mrdaliri

21

Dalla pagina a cui hai fatto riferimento:

Quando sollevi Http404 da una vista, Django caricherà una vista speciale dedicata alla gestione degli errori 404. Lo trova cercando la variabile handler404 nel tuo URLconf di root (e solo nel tuo URLconf di root; l'impostazione di handler404 in qualsiasi altro luogo non avrà alcun effetto), che è una stringa nella sintassi puntata di Python, lo stesso formato utilizzato dai normali callback URLconf. Una visualizzazione 404 in sé non ha nulla di speciale: è solo una visualizzazione normale.

Quindi credo che tu debba aggiungere qualcosa del genere al tuo urls.py:

handler404 = 'views.my_404_view'

e simili per handler500.


Come ti sembra Mike? Oggi è il mio primo giorno con Django e sono ancora alle corde
Zac

2
@JimRilye Avrai bisogno di aggiungere una funzione 500 adatta alle tue viste e quindi fare riferimento a quella variabile. Quindi, sopra la urlpatterns = ...riga, aggiungi una riga che dice handler500 = 'views.handle500', quindi aggiungi un def handle500(request):a views.py che mostra il tuo 500.html.
Mike Pelley

18

Se tutto ciò di cui hai bisogno è mostrare pagine personalizzate che hanno alcuni messaggi di errore fantasiosi per il tuo sito quando DEBUG = False, aggiungi due modelli denominati 404.html e 500.html nella directory dei modelli e raccoglierà automaticamente queste pagine personalizzate quando un 404 o 500 viene sollevato.


1
Funziona solo assicurati di avere qualcosa come: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]nella tua lista di MODELLI in settings.py.
eric

12

In Django 2. * puoi usare questa costruzione in views.py

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

In settings.py

DEBUG = False

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

if DEBUG is True:
    ALLOWED_HOSTS = []

In urls.py

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

Di solito creo default_app e gestisco errori a livello di sito, processori di contesto in esso.


Lavora per me. Ma qual è il exception?
zeleven

Secondo il collegamento alla documentazione: docs.djangoproject.com/en/2.1/ref/urls/… . È scritto: assicurati che il gestore accetti richieste ed eccezioni
Alouani Younes

1
Ha funzionato per me in Django 3.0 . Ma cos'è locals()? Il file mostra solo pass.
Enchance

9

settings.py:

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

e aggiungi le tue pagine 404.htmle 500.htmlnella cartella dei modelli. rimuovere 404.htmle 500.htmldai modelli nell'app sondaggi.


Come utilizzare il messaggio di raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} è anche disponibile.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

TEMPLATE_DEBUG è stato rimosso da django2 docs.quantifiedcode.com/python-anti-patterns/django/1.8/…
Steve W

7

Fai un errore, nella pagina degli errori scopri da dove django sta caricando i modelli, intendo lo stack del percorso template_dir aggiungi queste pagine html 500.html , 404.html . Quando si verificano questi errori, i rispettivi file modello verranno caricati automaticamente.

Puoi aggiungere pagine anche per altri codici di errore, come 400 e 403 .

Spero che questo aiuto !!!


6

In Django 3.x, la risposta accettata non funzionerà perchérender_to_response è stata rimossa completamente e sono state apportate ulteriori modifiche rispetto alla versione per cui ha funzionato la risposta accettata.

Ci sono anche altre risposte, ma sto presentando una risposta un po 'più pulita:

Nel tuo urls.pyfile principale :

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

Nel yourapp/views.pyfile:

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

Assicurati di aver importato render()nel yourapp/views.pyfile:

from django.shortcuts import render

Nota a margine : è render_to_response()stato deprecato in Django 2.xed è stato completamente rimosso nella versione 3.x.


5

Come una singola riga (per la pagina generica 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
E dove usarlo?
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' 

Funziona su django 2.0

Assicurati di includere il tuo personalizzato 404.htmlnella cartella dei modelli di app.


4

Django 3.0

ecco il link come personalizzare le visualizzazioni degli errori

ecco il collegamento su come rendere una vista

in urls.py(quello principale, nella cartella del progetto), inserire:

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 in quell'app ( my_app_name) inserisci 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è il percorso se si posizionano i file nella cartella dei modelli dei progetti (non delle app), templates/errors/404.htmlquindi posizionare i file dove si desidera e scrivere il percorso corretto.

NOTA 2: dopo il ricaricamento della pagina, se si vede ancora il vecchio modello, modificarlo settings.py DEBUG=True, salvarlo e poi di nuovo su False(per riavviare il server e raccogliere i nuovi file).


Nota aggiuntiva: se stai eseguendo i DEUB=Falsetuoi file statici, i file statici potrebbero non essere serviti, in modo da non poter visualizzare in anteprima le modifiche al modello di errore personalizzato. Usa ./manage.py runserver --insecureper forzare Django a servirli comunque.
Rob il


3

Prova a spostare i modelli di errore in .../Django/mysite/templates/?

Sono sicuro di questo, ma penso che debbano essere "globali" per il sito web.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.