Fixed #18807 -- Made 404.html and 500.html optional
Thanks Aymeric Augustin for the report and Jannis Leidel for the review.
This commit is contained in:
parent
864a0514b8
commit
8bd7b598b6
|
@ -1,6 +1,6 @@
|
|||
from django import http
|
||||
from django.template import (Context, RequestContext,
|
||||
loader, TemplateDoesNotExist)
|
||||
loader, Template, TemplateDoesNotExist)
|
||||
from django.views.decorators.csrf import requires_csrf_token
|
||||
|
||||
|
||||
|
@ -17,8 +17,13 @@ def page_not_found(request, template_name='404.html'):
|
|||
request_path
|
||||
The path of the requested URL (e.g., '/app/pages/bad_page/')
|
||||
"""
|
||||
t = loader.get_template(template_name) # You need to create a 404.html template.
|
||||
return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
|
||||
try:
|
||||
template = loader.get_template(template_name)
|
||||
except TemplateDoesNotExist:
|
||||
template = Template(
|
||||
'<h1>Not Found</h1>'
|
||||
'<p>The requested URL {{ request_path }} was not found on this server.</p>')
|
||||
return http.HttpResponseNotFound(template.render(RequestContext(request, {'request_path': request.path})))
|
||||
|
||||
|
||||
@requires_csrf_token
|
||||
|
@ -29,8 +34,11 @@ def server_error(request, template_name='500.html'):
|
|||
Templates: :template:`500.html`
|
||||
Context: None
|
||||
"""
|
||||
t = loader.get_template(template_name) # You need to create a 500.html template.
|
||||
return http.HttpResponseServerError(t.render(Context({})))
|
||||
try:
|
||||
template = loader.get_template(template_name)
|
||||
except TemplateDoesNotExist:
|
||||
return http.HttpResponseServerError('<h1>Server Error (500)</h1>')
|
||||
return http.HttpResponseServerError(template.render(Context({})))
|
||||
|
||||
|
||||
# This can be called when CsrfViewMiddleware.process_view has not run,
|
||||
|
|
|
@ -366,11 +366,10 @@ special: It's just a normal view.
|
|||
|
||||
You normally won't have to bother with writing 404 views. If you don't set
|
||||
``handler404``, the built-in view :func:`django.views.defaults.page_not_found`
|
||||
is used by default. In this case, you still have one obligation: create a
|
||||
``404.html`` template in the root of your template directory. The default 404
|
||||
view will use that template for all 404 errors. If :setting:`DEBUG` is set to
|
||||
``False`` (in your settings module) and if you didn't create a ``404.html``
|
||||
file, an ``Http500`` is raised instead. So remember to create a ``404.html``.
|
||||
is used by default. Optionally, you can create a ``404.html`` template
|
||||
in the root of your template directory. The default 404 view will then use that
|
||||
template for all 404 errors when :setting:`DEBUG` is set to ``False`` (in your
|
||||
settings module).
|
||||
|
||||
A couple more things to note about 404 views:
|
||||
|
||||
|
|
|
@ -158,9 +158,7 @@ For more on middleware, read the :doc:`middleware docs
|
|||
:class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`
|
||||
only steps in once another view has successfully produced a 404 response.
|
||||
If another view or middleware class attempts to produce a 404 but ends up
|
||||
raising an exception instead (such as a ``TemplateDoesNotExist``
|
||||
exception if your site does not have an appropriate template to
|
||||
use for HTTP 404 responses), the response will become an HTTP 500
|
||||
raising an exception instead, the response will become an HTTP 500
|
||||
("Internal Server Error") and the
|
||||
:class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`
|
||||
will not attempt to serve a flat page.
|
||||
|
|
|
@ -185,6 +185,12 @@ Django 1.5 also includes several smaller improvements worth noting:
|
|||
look up permissions by using ``{% if 'someapp.someperm' in perms %}``
|
||||
in templates.
|
||||
|
||||
* It's not required any more to have ``404.html`` and ``500.html`` templates in
|
||||
the root templates directory. Django will output some basic error messages for
|
||||
both situations when those templates are not found. Of course, it's still
|
||||
recommended as good practice to provide those templates in order to present
|
||||
pretty error pages to the user.
|
||||
|
||||
Backwards incompatible changes in 1.5
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -134,13 +134,12 @@ The 404 (page not found) view
|
|||
|
||||
When you raise an ``Http404`` exception, Django loads a special view devoted
|
||||
to handling 404 errors. By default, it's the view
|
||||
``django.views.defaults.page_not_found``, which loads and renders the template
|
||||
``404.html``.
|
||||
``django.views.defaults.page_not_found``, which either produces a very simple
|
||||
"Not Found" message or loads and renders the template ``404.html`` if you
|
||||
created it in your root template directory.
|
||||
|
||||
This means you need to define a ``404.html`` template in your root template
|
||||
directory. This template will be used for all 404 errors. The default 404 view
|
||||
will pass one variable to the template: ``request_path``, which is the URL
|
||||
that resulted in the error.
|
||||
The default 404 view will pass one variable to the template: ``request_path``,
|
||||
which is the URL that resulted in the error.
|
||||
|
||||
The ``page_not_found`` view should suffice for 99% of Web applications, but if
|
||||
you want to override it, you can specify ``handler404`` in your URLconf, like
|
||||
|
@ -152,15 +151,11 @@ Behind the scenes, Django determines the 404 view by looking for
|
|||
``handler404`` in your root URLconf, and falling back to
|
||||
``django.views.defaults.page_not_found`` if you did not define one.
|
||||
|
||||
Four things to note about 404 views:
|
||||
Three things to note about 404 views:
|
||||
|
||||
* The 404 view is also called if Django doesn't find a match after
|
||||
checking every regular expression in the URLconf.
|
||||
|
||||
* If you don't define your own 404 view — and simply use the default,
|
||||
which is recommended — you still have one obligation: you must create a
|
||||
``404.html`` template in the root of your template directory.
|
||||
|
||||
* The 404 view is passed a :class:`~django.template.RequestContext` and
|
||||
will have access to variables supplied by your
|
||||
:setting:`TEMPLATE_CONTEXT_PROCESSORS` setting (e.g., ``MEDIA_URL``).
|
||||
|
@ -176,13 +171,12 @@ The 500 (server error) view
|
|||
|
||||
Similarly, Django executes special-case behavior in the case of runtime errors
|
||||
in view code. If a view results in an exception, Django will, by default, call
|
||||
the view ``django.views.defaults.server_error``, which loads and renders the
|
||||
template ``500.html``.
|
||||
the view ``django.views.defaults.server_error``, which either produces a very
|
||||
simple "Server Error" message or loads and renders the template ``500.html`` if
|
||||
you created it in your root template directory.
|
||||
|
||||
This means you need to define a ``500.html`` template in your root template
|
||||
directory. This template will be used for all server errors. The default 500
|
||||
view passes no variables to this template and is rendered with an empty
|
||||
``Context`` to lessen the chance of additional errors.
|
||||
The default 500 view passes no variables to the ``500.html`` template and is
|
||||
rendered with an empty ``Context`` to lessen the chance of additional errors.
|
||||
|
||||
This ``server_error`` view should suffice for 99% of Web applications, but if
|
||||
you want to override the view, you can specify ``handler500`` in your URLconf,
|
||||
|
@ -194,11 +188,7 @@ Behind the scenes, Django determines the 500 view by looking for
|
|||
``handler500`` in your root URLconf, and falling back to
|
||||
``django.views.defaults.server_error`` if you did not define one.
|
||||
|
||||
Two things to note about 500 views:
|
||||
|
||||
* If you don't define your own 500 view — and simply use the default,
|
||||
which is recommended — you still have one obligation: you must create a
|
||||
``500.html`` template in the root of your template directory.
|
||||
One thing to note about 500 views:
|
||||
|
||||
* If :setting:`DEBUG` is set to ``True`` (in your settings module), then
|
||||
your 500 view will never be used, and the traceback will be displayed
|
||||
|
|
|
@ -229,11 +229,11 @@ class Templates(unittest.TestCase):
|
|||
loader.template_source_loaders = (filesystem.Loader(),)
|
||||
|
||||
# We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
|
||||
# point to a directory containing a 404.html file. Also that
|
||||
# point to a directory containing a login.html file. Also that
|
||||
# the file system and app directories loaders both inherit the
|
||||
# load_template method from the BaseLoader class, so we only need
|
||||
# to test one of them.
|
||||
load_name = '404.html'
|
||||
load_name = 'login.html'
|
||||
template = loader.get_template(load_name)
|
||||
template_name = template.nodelist[0].source[0].name
|
||||
self.assertTrue(template_name.endswith(load_name),
|
||||
|
|
|
@ -628,15 +628,6 @@ class TemplateExceptionTests(TestCase):
|
|||
if hasattr(template_loader, 'reset'):
|
||||
template_loader.reset()
|
||||
|
||||
@override_settings(TEMPLATE_DIRS=(),)
|
||||
def test_no_404_template(self):
|
||||
"Missing templates are correctly reported by test client"
|
||||
try:
|
||||
response = self.client.get("/no_such_view/")
|
||||
self.fail("Should get error about missing template")
|
||||
except TemplateDoesNotExist:
|
||||
pass
|
||||
|
||||
@override_settings(
|
||||
TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'bad_templates'),)
|
||||
)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from django.test.utils import setup_test_template_loader, restore_template_loaders
|
||||
|
||||
from ..models import Author, Article, UrlArticle
|
||||
|
||||
|
@ -71,6 +72,23 @@ class DefaultsTests(TestCase):
|
|||
response = self.client.get('/views/server_error/')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
|
||||
def test_custom_templates(self):
|
||||
"""
|
||||
Test that 404.html and 500.html templates are picked by their respective
|
||||
handler.
|
||||
"""
|
||||
setup_test_template_loader(
|
||||
{'404.html': 'This is a test template for a 404 error.',
|
||||
'500.html': 'This is a test template for a 500 error.'}
|
||||
)
|
||||
try:
|
||||
for code, url in ((404, '/views/non_existing_url/'), (500, '/views/server_error/')):
|
||||
response = self.client.get(url)
|
||||
self.assertContains(response, "test template for a %d error" % code,
|
||||
status_code=code)
|
||||
finally:
|
||||
restore_template_loaders()
|
||||
|
||||
def test_get_absolute_url_attributes(self):
|
||||
"A model can set attributes on the get_absolute_url method"
|
||||
self.assertTrue(getattr(UrlArticle.get_absolute_url, 'purge', False),
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Django Internal Tests: 404 Error
|
|
@ -1 +0,0 @@
|
|||
Django Internal Tests: 500 Error
|
Loading…
Reference in New Issue