Django, création d'une page d'erreur 500/404 personnalisée


105

En suivant exactement le didacticiel trouvé ici , je ne peux pas créer de page d'erreur 500 ou 404 personnalisée. Si je tape une mauvaise URL, la page me donne la page d'erreur par défaut. Y a-t-il quelque chose que je devrais vérifier qui empêcherait une page personnalisée de s'afficher?

Répertoires de fichiers:

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

dans mysite / settings.py je les ai activés:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

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

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

Je peux publier tout autre code nécessaire, mais que dois-je changer pour obtenir une page d'erreur 500 personnalisée si j'utilise une mauvaise URL?

Éditer

SOLUTION: j'avais un supplément

TEMPLATE_DIRS

dans mon settings.py et cela causait le problème


1
Le débogage est défini sur False dans mon code
Zac


1
J'ai trouvé cette réponse en cherchant le moyen de créer uniquement un modèle personnalisé et je voulais partager un peu de documentation Django qui m'a beaucoup aidé; docs.djangoproject.com/en/1.7/ref/views/…
Blackeagle52

Le mien a fonctionné sans le paramètre template_dirs.
Programmingjoe

1
Il faut ironiser quand le lien de la première ligne mène à la page 404 de Django. Mène à une page de tutoriel pour une version de Django qui n'existe pas je pense. Voici le lien vers la page du tutoriel pour Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03
andrewec

Réponses:


120

Sous votre principale, views.pyajoutez votre propre implémentation personnalisée des deux vues suivantes, et configurez simplement les modèles 404.html et 500.html avec ce que vous souhaitez afficher.

Avec cette solution, aucun code personnalisé ne doit être ajouté à urls.py

Voici le code:

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

Mettre à jour

handler404et handler500sont exportées les variables de configuration de chaîne Django trouvées dans django/conf/urls/__init__.py. C'est pourquoi la configuration ci-dessus fonctionne.

Pour que la configuration ci-dessus fonctionne, vous devez définir les variables suivantes dans votre urls.pyfichier et pointer les variables Django exportées vers la chaîne de chemin Python d'où ces vues fonctionnelles Django sont définies, comme ceci:

# project/urls.py

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

Mise à jour pour Django 2.0

Les signatures des vues des gestionnaires ont été modifiées dans Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

Si vous utilisez des vues comme ci-dessus, handler404 échouera avec le message:

"handler404 () a obtenu un argument de mot clé inattendu 'exception'"

Dans ce cas, modifiez vos vues comme ceci:

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

Cela semblait fonctionner assez bien pour moi, mais pour une raison quelconque, request.user apparaît bien dans le modèle 404, mais pas du tout dans le modèle 500 (et ils sont presque identiques) - question posée à ce sujet ici: stackoverflow.com/ questions / 26043211 /…
Gravity Grave

1
Une autre chose sur laquelle je me demandais - et si vous utilisez le backend d'administration et que vous souhaitez utiliser des modèles séparés pour ceux-ci? À ma connaissance, l'administrateur n'a pas de vues.py pour remplacer et mettre ce morceau de code.
Gravity Grave

11
@GravityGrave 500 templatene sera pas rendu request.usercar il signale une erreur de serveur 500, donc le serveur ne peut rien servir.
Aaron Lelevier

5
Cela n'a pas fonctionné pour moi avec django 1.9; (Peut-être que je fais quelque chose de mal. Handler404 est-il le nom réservé de django? Comment django saurait-il qu'il devrait appeler exactement cette vue?
deathangel908

1
J'ai mis à jour la réponse en fonction de votre commentaire. Désolé que la mise à jour soit si tardive. J'espère que ca aide.
Aaron Lelevier

71

Réponse officielle:

Voici le lien vers la documentation officielle sur la façon de configurer des vues d'erreur personnalisées:

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

Il dit d'ajouter des lignes comme celles-ci dans votre URLconf (les définir n'importe où ailleurs n'aura aucun effet):

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'

Vous pouvez également personnaliser la vue des erreurs CSRF en modifiant le paramètre CSRF_FAILURE_VIEW.

Gestionnaires d'erreurs par défaut:

Il vaut la peine de lire la documentation des gestionnaires d'erreur par défaut, page_not_found, server_error, permission_deniedet bad_request. Par défaut, ils utilisent ces modèles s'ils peuvent les trouver, respectivement 404.html, 500.html, 403.htmlet 400.html.

Donc, si tout ce que vous voulez faire est de créer de jolies pages d'erreur, créez simplement ces fichiers dans un TEMPLATE_DIRSrépertoire, vous n'avez pas du tout besoin d'éditer URLConf. Lisez la documentation pour voir quelles variables de contexte sont disponibles.

Dans Django 1.10 et versions ultérieures, la vue d'erreur CSRF par défaut utilise le modèle 403_csrf.html.

Je t'ai eu:

N'oubliez pas qu'il DEBUGdoit être défini sur False pour que ceux-ci fonctionnent, sinon les gestionnaires de débogage normaux seront utilisés.


1
J'ai ajouté, mais cela ne fonctionne pas. Ajout du handler404 et d'autres pointant vers les bons endroits dans mes vues, mais cela ne fonctionne pas, je vois toujours la valeur par défaut 404. Et oui, je suis en mode Debug False et
j'utilise

En utilisant Django 1.9 et en ajoutant simplement 500.html, etc. les modèles les affichent à la place des pages standard. Belle solution facile.
Curtisp le

2
Gotcha m'a aidé. Cela a fonctionné en apportant ces modifications dans mes paramètres.py, définissez DEBUG = False et ALLOWED_HOSTS = ['0.0.0.0'] pour accepter la requête http de n'importe quel client.
shaffooo

1
Juste au cas où quelqu'un d'autre se demanderait où se trouve URLconf, le voici
Arthur Tarasov

38

Ajoutez ces lignes dans 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'

# ...

et implémentez nos vues personnalisées dans 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
Pourquoi importeriez-vous handler400uniquement pour l'écraser avec handler400 = 'myapp.views.bad_request'?
Flimm le


5
Vous n'avez pas besoin d'importer les gestionnaires ici pour les remplacer.
funkotron

1
Vous ne devriez pas utiliser render_to_response. D'après la documentation: "Ce n'est pas recommandé et sera probablement obsolète à l'avenir."
Timmy O'Mahony

Pour Django 1.10, comme cela render_to_responseva être obsolète, voir ce qui suit (à utiliser à la renderplace): stackoverflow.com/questions/44228397/…
mrdaliri

21

À partir de la page que vous avez référencée:

Lorsque vous augmentez Http404 depuis une vue, Django chargera une vue spéciale consacrée à la gestion des erreurs 404. Il le trouve en recherchant la variable handler404 dans votre URLconf racine (et uniquement dans votre URLconf racine; définir handler404 n'importe où ailleurs n'aura aucun effet), qui est une chaîne en syntaxe pointillée Python - le même format que les rappels URLconf normaux utilisent. Une vue 404 elle-même n'a rien de spécial: c'est juste une vue normale.

Je pense donc que vous devez ajouter quelque chose comme ceci à votre urls.py:

handler404 = 'views.my_404_view'

et similaire pour handler500.


A quoi ça ressemble Mike? Aujourd'hui, c'est mon premier jour avec Django et je m'accroche toujours aux cordes
Zac

2
@JimRilye Vous devrez ajouter une fonction 500 appropriée à vos vues, puis la référencer avec cette variable. Donc, au-dessus de votre urlpatterns = ...ligne, ajoutez une ligne qui dit handler500 = 'views.handle500', puis ajoutez un def handle500(request):à votre views.py qui affiche votre 500.html.
Mike Pelley

18

Si tout ce dont vous avez besoin est d'afficher des pages personnalisées DEBUG = Falsecontenant des messages d'erreur sophistiqués pour votre site , ajoutez deux modèles nommés 404.html et 500.html dans votre répertoire de modèles et il récupérera automatiquement ces pages personnalisées lorsqu'un 404 ou 500 est soulevé.


1
Cela fonctionne juste assurez-vous que vous avez quelque chose comme: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')]dans votre liste de modèles dans settings.py.
eric

12

Dans Django 2. *, vous pouvez utiliser cette construction dans views.py

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

Dans settings.py

DEBUG = False

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

if DEBUG is True:
    ALLOWED_HOSTS = []

Dans urls.py

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

Habituellement, je crée default_app et gère les erreurs à l'échelle du site, les processeurs de contexte.


Travaille pour moi. Mais quel est le exception?
zeleven

Selon le lien de la documentation: docs.djangoproject.com/en/2.1/ref/urls/… . C'est écrit: assurez-vous que le gestionnaire accepte les arguments de requête et d'exception
Alouani Younes

1
A travaillé pour moi dans Django 3.0 . Mais qu'est-ce que c'est locals()? Le fichier s'affiche uniquement pass.
enchance le

9

settings.py:

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

et ajoutez simplement vos pages 404.htmlet 500.htmldans le dossier des modèles. supprimer 404.htmlet 500.htmldes modèles dans l'application de sondages.


Comment utiliser le message de raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} est également disponible.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

TEMPLATE_DEBUG est supprimé de django2 docs.quantifiedcode.com/python-anti-patterns/django/1.8
Steve W

7

Faire une erreur, Sur la page d'erreur, découvrez d'où django charge les modèles, je veux dire la pile de chemins.Dans la base template_dir, ajoutez ces pages html 500.html , 404.html . Lorsque ces erreurs se produisent, les fichiers de modèle respectifs seront automatiquement chargés.

Vous pouvez également ajouter des pages pour d'autres codes d'erreur, comme 400 et 403 .

J'espère que cette aide !!!


6

Dans Django 3.x, la réponse acceptée ne fonctionnera pas car elle render_to_responsea été complètement supprimée et d'autres modifications ont été apportées depuis la version pour laquelle la réponse acceptée fonctionnait.

Quelques autres réponses sont également là mais je présente une réponse un peu plus claire:

Dans votre urls.pyfichier principal :

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

Dans le yourapp/views.pydossier:

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

Assurez-vous que vous avez importé render()dans le yourapp/views.pyfichier:

from django.shortcuts import render

Note latérale: render_to_response()était obsolète dans Django 2.xet il a été complètement supprimé dans la version 3.x.


5

En une seule ligne (pour la page générique 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
Et où l'utiliser?
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' 

Cela fonctionne sur django 2.0

Assurez-vous d'inclure votre personnalisation 404.htmldans le dossier des modèles d'application.


4

Django 3.0

voici un lien comment personnaliser les vues d'erreur

voici le lien comment rendre une vue

dans le urls.py(le principal, dans le dossier du projet), mettez:

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'

et dans cette application ( my_app_name), insérez 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", {})

REMARQUE: error/404.htmlest le chemin si vous placez vos fichiers dans le dossier de modèles de projets (pas dans les applications) templates/errors/404.html, veuillez donc placer les fichiers où vous le souhaitez et écrivez le bon chemin.

REMARQUE 2: après le rechargement de la page, si vous voyez toujours l'ancien modèle, modifiez-le settings.py DEBUG=True, enregistrez-le, puis à nouveau dans False(pour redémarrer le serveur et collecter les nouveaux fichiers).


Remarque supplémentaire: si vous exécutez dans DEUB=Falsevos fichiers statiques peuvent ne pas être servis, ce qui vous empêche de prévisualiser les modifications de votre modèle d'erreur personnalisé. Utilisez ./manage.py runserver --insecurepour forcer Django à les servir quand même.
Rob


3

Essayez de déplacer vos modèles d'erreur vers .../Django/mysite/templates/?

Je suis sûr de celui-ci, mais je pense que ceux-ci doivent être "globaux" pour le site Web.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.