ChatGPT解决这个技术问题 Extra ChatGPT

Django, creating a custom 500/404 error page

Following the tutorial found here exactly, I cannot create a custom 500 or 404 error page. If I do type in a bad url, the page gives me the default error page. Is there anything I should be checking for that would prevent a custom page from showing up?

File directories:

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

within mysite/settings.py I have these enabled:

DEBUG = False
TEMPLATE_DEBUG = DEBUG

#....

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

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

I can post any other code necessary, but what should I be changing to get a custom 500 error page if I use a bad url?

Edit

SOLUTION: I had an additional

TEMPLATE_DIRS

within my settings.py and that was causing the problem

Debug is set to False in my code
Found this answer while looking for the way to make only a custom template and I wanted to share a bit of Django documentation which helped me a lot; docs.djangoproject.com/en/1.7/ref/views/…
Mine worked without the template_dirs setting.
Points for irony when link in first line leads to Django's 404 page. Leads to a tutorial page for a version of Django that doesn't exist I think. Here is the link to the tutorial page for Django 2.0: docs.djangoproject.com/en/2.0/intro/tutorial03

P
Pablo Castellano

Under your main views.py add your own custom implementation of the following two views, and just set up the templates 404.html and 500.html with what you want to display.

With this solution, no custom code needs to be added to urls.py

Here's the 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

Update

handler404 and handler500 are exported Django string configuration variables found in django/conf/urls/__init__.py. That is why the above config works.

To get the above config to work, you should define the following variables in your urls.py file and point the exported Django variables to the string Python path of where these Django functional views are defined, like so:

# project/urls.py

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

Update for Django 2.0

Signatures for handler views were changed in Django 2.0: https://docs.djangoproject.com/en/2.0/ref/views/#error-views

If you use views as above, handler404 will fail with message:

"handler404() got an unexpected keyword argument 'exception'"

In such case modify your views like this:

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

Another thing I was wondering about -- what if you use the admin backend and want to use separate templates for those? To my knowledge, admin doesn't have a views.py to override and put this bit of code in.
@GravityGrave the 500 template won't render request.user because it is reporting a 500 server error, so the server is not able to serve up anything.
Didn't work for me with django 1.9 ;( Maybe I'm doing something wrong. Is handler404 django reserved name? How would django know that it should call exactly that view?
I updated the answer based on your comment. Sorry that the update is so late. I hope that this helps.
render_to_response was replaced by render in Django 3.0, which automatically uses RequestContext, simplifying this answer's example code
F
Flimm

Official answer:

Here is the link to the official documentation on how to set up custom error views:

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

It says to add lines like these in your URLconf (setting them anywhere else will have no effect):

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'

You can also customise the CSRF error view by modifying the setting CSRF_FAILURE_VIEW.

Default error handlers:

It's worth reading the documentation of the default error handlers, page_not_found, server_error, permission_denied and bad_request. By default, they use these templates if they can find them, respectively: 404.html, 500.html, 403.html, and 400.html.

So if all you want to do is make pretty error pages, just create those files in a TEMPLATE_DIRS directory, you don't need to edit URLConf at all. Read the documentation to see which context variables are available.

In Django 1.10 and later, the default CSRF error view uses the template 403_csrf.html.

Gotcha:

Don't forget that DEBUG must be set to False for these to work, otherwise, the normal debug handlers will be used.


I did add, but it doesn't work. Added the handler404 and others pointing to right places in my views, yet it doesn't work, still seeing the default 404. And yes, I'm in Debug False mode and using 1.9
Using Django 1.9 and simply adding 500.html etc templates shows them instead of standard pages. Nice easy fix.
Gotcha helped me. It worked by making these changes in my settings.py, set DEBUG=False and ALLOWED_HOSTS = ['0.0.0.0'] to accept http request from any client.
Just in case anyone else is wondering where on earth is URLconf, here it is
@ArthurTarasov Yeah, would've been better to reference urls.py file along with it haha.
M
MD. Khairul Basar

Add these lines 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'

# ...

and implement our custom views 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

# ...

Why would you import handler400 only to overwrite it with handler400 = 'myapp.views.bad_request'?
You don't need to import the handlers here in order to override them.
You shouldn't use render_to_response. From the docs: "it’s not recommended and is likely to be deprecated in the future."
For Django 1.10, as render_to_response is going to be deprecated, see following (use render instead): stackoverflow.com/questions/44228397/…
e
elano7

Django 3.0+ 4.0+

here is link how to customize error views

here is link how to render a view

in the urls.py (the main one, in project folder), put:

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'

and in the mentioned app (my_app_name) put in the 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", {})

NOTE: errors/404.html is the path if you place your files into the projects (not the apps) template foldertemplates/errors/404.html so please place the files where you want and write the right path.

NOTE 2: After page reload, if you still see the old template, change in settings.py DEBUG=True, save it, and then again to False and save again (that will restart the server and collect the new files).


Extra note: If you are running in DEUB=False your static files may not be served, making it so you can't preview your custom error template changes. Use ./manage.py runserver --insecure to get force django to serve them anyway.
Very well explained!
You need to add status=<status_code> parameter to render() calls, otherwise you will get status 200 in the responses. E.g. status=500 for a 500 page.
yeah. very important, no matter what 404 pages you have and how good they are setup, you need to disable DEBUG in order to see your custom 404 page, this is more like a production only feature (the 404 page)
M
Mike Pelley

From the page you referenced:

When you raise Http404 from within a view, Django will load a special view devoted to handling 404 errors. It finds it by looking for the variable handler404 in your root URLconf (and only in your root URLconf; setting handler404 anywhere else will have no effect), which is a string in Python dotted syntax – the same format the normal URLconf callbacks use. A 404 view itself has nothing special: It’s just a normal view.

So I believe you need to add something like this to your urls.py:

handler404 = 'views.my_404_view'

and similar for handler500.


How does that look Mike? Today is my first day using Django and I'm still hanging onto the ropes
@JimRilye You'll need to add a suitable 500 function to your views, and then reference it with that variable. So, above your urlpatterns = ... line, add a line that says handler500 = 'views.handle500', and then add a def handle500(request): to your views.py that displays your 500.html.
K
Krishna G Nair

If all you need is to show custom pages which have some fancy error messages for your site when DEBUG = False, then add two templates named 404.html and 500.html in your templates directory and it will automatically pick up this custom pages when a 404 or 500 is raised.


This works just make sure you have something like: 'DIRS': [os.path.join(BASE_DIR, '<project_name>/templates')] in your TEMPLATES list in settings.py.
R
Rehmat

In Django 3.x, the accepted answer won't work because render_to_response has been removed completely as well as some more changes have been made since the version the accepted answer worked for.

Some other answers are also there but I'm presenting a little cleaner answer:

In your main urls.py file:

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

In yourapp/views.py file:

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

Ensure that you have imported render() in yourapp/views.py file:

from django.shortcuts import render

Side note: render_to_response() was deprecated in Django 2.x and it has been completely removed in verision 3.x.


A
Anuj TBE

No additional view is required. https://docs.djangoproject.com/en/3.0/ref/views/

Just put the error files in the root of templates directory

404.html

400.html

403.html

500.html

And it should use your error page when debug is False


P
Paolo

settings.py:

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

and just add your 404.html and 500.html pages in templates folder. remove 404.html and 500.html from templates in polls app.


How to use message of raise Http404('msg'): stackoverflow.com/a/37109914/895245 {{ request_path }} is also available.
TEMPLATE_DEBUG is removed from django2 docs.quantifiedcode.com/python-anti-patterns/django/1.8/…
post 1.8: correct way to debug templates here
D
Denis

In Django 2.* you can use this construction 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'

Usually i creating default_app and handle site-wide errors, context processors in it.


Work for me. But what is the exception?
According to the documentation link : docs.djangoproject.com/en/2.1/ref/urls/…. It's written : make sure the handler accepts request and exception arguments
Worked for me in Django 3.0. But what is locals()? The file only shows pass.
A
ALLSYED

Make an error, On the error page find out from where django is loading templates.I mean the path stack.In base template_dir add these html pages 500.html , 404.html. When these errors occur the respective template files will be automatically loaded.

You can add pages for other error codes too, like 400 and 403.

Hope this help !!!


F
Francois

As one single line (for 404 generic page):

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)

And where to use it?
a
ayhan
# 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' 

This works on django 2.0

Be sure to include your custom 404.html inside the app templates folder.


a
astrognocci

Try moving your error templates to .../Django/mysite/templates/ ?

I'm note sure about this one, but i think these need to be "global" to the website.


P
Praveen Kumar

In Django root urls.py file, add the below lines

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

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

In your app's views.py file, create the respective functions.

def server_error(request, exception=None):
    # return render(request, '500.html')
    return redirect('/')

Finally, in your settings.py file, set DEBUG = False


M
Majid

in urls.py please enter this code:

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

handler404 = 'my_app.views.page_not_found_view'

then add this code in your views.py

from django.shortcuts import render,get_object_or_404
def page_not_found_view(request, exception):
    return render(request, '404.html', status=404)

Dont forget to set DEBUG = False and Also set ALLOWED_HOSTS = [127.0.0.1] while you are testing in your laptop


关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now