diff --git a/django/views/defaults.py b/django/views/defaults.py
index 2bbc233..ec7a233 100644
a
|
b
|
|
1 | 1 | from django import http |
2 | 2 | from django.template import (Context, RequestContext, |
3 | | loader, TemplateDoesNotExist) |
| 3 | loader, Template, TemplateDoesNotExist) |
4 | 4 | from django.views.decorators.csrf import requires_csrf_token |
5 | 5 | |
6 | 6 | |
… |
… |
def page_not_found(request, template_name='404.html'):
|
17 | 17 | request_path |
18 | 18 | The path of the requested URL (e.g., '/app/pages/bad_page/') |
19 | 19 | """ |
20 | | t = loader.get_template(template_name) # You need to create a 404.html template. |
21 | | return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path}))) |
| 20 | try: |
| 21 | template = loader.get_template(template_name) |
| 22 | except TemplateDoesNotExist: |
| 23 | template = Template( |
| 24 | '<h1>Not Found</h1>' |
| 25 | '<p>The requested URL {{ request_path }} was not found on this server.</p>') |
| 26 | return http.HttpResponseNotFound(template.render(RequestContext(request, {'request_path': request.path}))) |
22 | 27 | |
23 | 28 | |
24 | 29 | @requires_csrf_token |
… |
… |
def server_error(request, template_name='500.html'):
|
29 | 34 | Templates: :template:`500.html` |
30 | 35 | Context: None |
31 | 36 | """ |
32 | | t = loader.get_template(template_name) # You need to create a 500.html template. |
33 | | return http.HttpResponseServerError(t.render(Context({}))) |
| 37 | try: |
| 38 | template = loader.get_template(template_name) |
| 39 | except TemplateDoesNotExist: |
| 40 | return http.HttpResponseServerError('<h1>Server Error (500)</h1>') |
| 41 | return http.HttpResponseServerError(template.render(Context({}))) |
34 | 42 | |
35 | 43 | |
36 | 44 | # This can be called when CsrfViewMiddleware.process_view has not run, |
diff --git a/docs/intro/tutorial03.txt b/docs/intro/tutorial03.txt
index 03d4bf6..b242de6 100644
a
|
b
|
special: It's just a normal view.
|
366 | 366 | |
367 | 367 | You normally won't have to bother with writing 404 views. If you don't set |
368 | 368 | ``handler404``, the built-in view :func:`django.views.defaults.page_not_found` |
369 | | is used by default. In this case, you still have one obligation: create a |
370 | | ``404.html`` template in the root of your template directory. The default 404 |
371 | | view will use that template for all 404 errors. If :setting:`DEBUG` is set to |
372 | | ``False`` (in your settings module) and if you didn't create a ``404.html`` |
373 | | file, an ``Http500`` is raised instead. So remember to create a ``404.html``. |
| 369 | is used by default. Optionally, you can create a ``404.html`` template |
| 370 | in the root of your template directory. The default 404 view will then use that |
| 371 | template for all 404 errors when :setting:`DEBUG` is set to ``False`` (in your |
| 372 | settings module). |
374 | 373 | |
375 | 374 | A couple more things to note about 404 views: |
376 | 375 | |
diff --git a/docs/ref/contrib/flatpages.txt b/docs/ref/contrib/flatpages.txt
index 3de4497..90822b4 100644
a
|
b
|
For more on middleware, read the :doc:`middleware docs
|
158 | 158 | :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` |
159 | 159 | only steps in once another view has successfully produced a 404 response. |
160 | 160 | If another view or middleware class attempts to produce a 404 but ends up |
161 | | raising an exception instead (such as a ``TemplateDoesNotExist`` |
162 | | exception if your site does not have an appropriate template to |
163 | | use for HTTP 404 responses), the response will become an HTTP 500 |
| 161 | raising an exception instead, the response will become an HTTP 500 |
164 | 162 | ("Internal Server Error") and the |
165 | 163 | :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` |
166 | 164 | will not attempt to serve a flat page. |
diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
index 6420239..6b11a8c 100644
a
|
b
|
Django 1.5 also includes several smaller improvements worth noting:
|
127 | 127 | configuration duplication. More information can be found in the |
128 | 128 | :func:`~django.contrib.auth.decorators.login_required` documentation. |
129 | 129 | |
| 130 | * It's not required any more to have ``404.html`` and ``500.html`` templates in |
| 131 | the root templates directory. Django will output some basic error messages for |
| 132 | both situations when those templates are not found. Of course, it's still |
| 133 | recommended as good practice to provide those templates in order to present |
| 134 | pretty error pages to the user. |
| 135 | |
130 | 136 | Backwards incompatible changes in 1.5 |
131 | 137 | ===================================== |
132 | 138 | |
diff --git a/docs/topics/http/views.txt b/docs/topics/http/views.txt
index c4bd15e..7c4d1bb 100644
a
|
b
|
The 404 (page not found) view
|
134 | 134 | |
135 | 135 | When you raise an ``Http404`` exception, Django loads a special view devoted |
136 | 136 | to handling 404 errors. By default, it's the view |
137 | | ``django.views.defaults.page_not_found``, which loads and renders the template |
138 | | ``404.html``. |
| 137 | ``django.views.defaults.page_not_found``, which either produces a very simple |
| 138 | "Not Found" message or loads and renders the template ``404.html`` if you |
| 139 | created it in your root template directory. |
139 | 140 | |
140 | | This means you need to define a ``404.html`` template in your root template |
141 | | directory. This template will be used for all 404 errors. The default 404 view |
142 | | will pass one variable to the template: ``request_path``, which is the URL |
143 | | that resulted in the error. |
| 141 | The default 404 view will pass one variable to the template: ``request_path``, |
| 142 | which is the URL that resulted in the error. |
144 | 143 | |
145 | 144 | The ``page_not_found`` view should suffice for 99% of Web applications, but if |
146 | 145 | you want to override it, you can specify ``handler404`` in your URLconf, like |
… |
… |
Behind the scenes, Django determines the 404 view by looking for
|
152 | 151 | ``handler404`` in your root URLconf, and falling back to |
153 | 152 | ``django.views.defaults.page_not_found`` if you did not define one. |
154 | 153 | |
155 | | Four things to note about 404 views: |
| 154 | Three things to note about 404 views: |
156 | 155 | |
157 | 156 | * The 404 view is also called if Django doesn't find a match after |
158 | 157 | checking every regular expression in the URLconf. |
159 | 158 | |
160 | | * If you don't define your own 404 view — and simply use the default, |
161 | | which is recommended — you still have one obligation: you must create a |
162 | | ``404.html`` template in the root of your template directory. |
163 | | |
164 | 159 | * The 404 view is passed a :class:`~django.template.RequestContext` and |
165 | 160 | will have access to variables supplied by your |
166 | 161 | :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting (e.g., ``MEDIA_URL``). |
… |
… |
The 500 (server error) view
|
176 | 171 | |
177 | 172 | Similarly, Django executes special-case behavior in the case of runtime errors |
178 | 173 | in view code. If a view results in an exception, Django will, by default, call |
179 | | the view ``django.views.defaults.server_error``, which loads and renders the |
180 | | template ``500.html``. |
| 174 | the view ``django.views.defaults.server_error``, which either produces a very |
| 175 | simple "Server Error" message or loads and renders the template ``500.html`` if |
| 176 | you created it in your root template directory. |
181 | 177 | |
182 | | This means you need to define a ``500.html`` template in your root template |
183 | | directory. This template will be used for all server errors. The default 500 |
184 | | view passes no variables to this template and is rendered with an empty |
185 | | ``Context`` to lessen the chance of additional errors. |
| 178 | The default 500 view passes no variables to the ``500.html`` template and is |
| 179 | rendered with an empty ``Context`` to lessen the chance of additional errors. |
186 | 180 | |
187 | 181 | This ``server_error`` view should suffice for 99% of Web applications, but if |
188 | 182 | you want to override the view, you can specify ``handler500`` in your URLconf, |
… |
… |
Behind the scenes, Django determines the 500 view by looking for
|
194 | 188 | ``handler500`` in your root URLconf, and falling back to |
195 | 189 | ``django.views.defaults.server_error`` if you did not define one. |
196 | 190 | |
197 | | Two things to note about 500 views: |
198 | | |
199 | | * If you don't define your own 500 view — and simply use the default, |
200 | | which is recommended — you still have one obligation: you must create a |
201 | | ``500.html`` template in the root of your template directory. |
| 191 | One thing to note about 500 views: |
202 | 192 | |
203 | 193 | * If :setting:`DEBUG` is set to ``True`` (in your settings module), then |
204 | 194 | your 500 view will never be used, and the traceback will be displayed |
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 41f40e7..a150d1c 100644
a
|
b
|
class Templates(unittest.TestCase):
|
229 | 229 | loader.template_source_loaders = (filesystem.Loader(),) |
230 | 230 | |
231 | 231 | # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to |
232 | | # point to a directory containing a 404.html file. Also that |
| 232 | # point to a directory containing a login.html file. Also that |
233 | 233 | # the file system and app directories loaders both inherit the |
234 | 234 | # load_template method from the BaseLoader class, so we only need |
235 | 235 | # to test one of them. |
236 | | load_name = '404.html' |
| 236 | load_name = 'login.html' |
237 | 237 | template = loader.get_template(load_name) |
238 | 238 | template_name = template.nodelist[0].source[0].name |
239 | 239 | self.assertTrue(template_name.endswith(load_name), |
diff --git a/tests/regressiontests/test_client_regress/tests.py b/tests/regressiontests/test_client_regress/tests.py
index d80293b..fdbf30d 100644
a
|
b
|
class TemplateExceptionTests(TestCase):
|
619 | 619 | if hasattr(template_loader, 'reset'): |
620 | 620 | template_loader.reset() |
621 | 621 | |
622 | | @override_settings(TEMPLATE_DIRS=(),) |
623 | | def test_no_404_template(self): |
624 | | "Missing templates are correctly reported by test client" |
625 | | try: |
626 | | response = self.client.get("/no_such_view/") |
627 | | self.fail("Should get error about missing template") |
628 | | except TemplateDoesNotExist: |
629 | | pass |
630 | | |
631 | 622 | @override_settings( |
632 | 623 | TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'bad_templates'),) |
633 | 624 | ) |
diff --git a/tests/regressiontests/views/tests/defaults.py b/tests/regressiontests/views/tests/defaults.py
index 2dd40b4..3ca7f79 100644
a
|
b
|
|
1 | | from __future__ import absolute_import |
| 1 | from __future__ import absolute_import, unicode_literals |
2 | 2 | |
3 | | from django.test import TestCase |
4 | 3 | from django.contrib.contenttypes.models import ContentType |
| 4 | from django.test import TestCase |
| 5 | from django.test.utils import setup_test_template_loader, restore_template_loaders |
5 | 6 | |
6 | 7 | from ..models import Author, Article, UrlArticle |
7 | 8 | |
… |
… |
class DefaultsTests(TestCase):
|
71 | 72 | response = self.client.get('/views/server_error/') |
72 | 73 | self.assertEqual(response.status_code, 500) |
73 | 74 | |
| 75 | def test_custom_templates(self): |
| 76 | """ |
| 77 | Test that 404.html and 500.html templates are picked by their respective |
| 78 | handler. |
| 79 | """ |
| 80 | setup_test_template_loader( |
| 81 | {'404.html': 'This is a test template for a 404 error.', |
| 82 | '500.html': 'This is a test template for a 500 error.'} |
| 83 | ) |
| 84 | try: |
| 85 | for code, url in ((404, '/views/non_existing_url/'), (500, '/views/server_error/')): |
| 86 | response = self.client.get(url) |
| 87 | self.assertContains(response, "test template for a %d error" % code, |
| 88 | status_code=code) |
| 89 | finally: |
| 90 | restore_template_loaders() |
| 91 | |
74 | 92 | def test_get_absolute_url_attributes(self): |
75 | 93 | "A model can set attributes on the get_absolute_url method" |
76 | 94 | self.assertTrue(getattr(UrlArticle.get_absolute_url, 'purge', False), |
diff --git a/tests/templates/404.html b/tests/templates/404.html
deleted file mode 100644
index da627e2..0000000
+
|
-
|
|
1 | | Django Internal Tests: 404 Error |
2 | | No newline at end of file |
diff --git a/tests/templates/500.html b/tests/templates/500.html
deleted file mode 100644
index ff028cb..0000000
+
|
-
|
|
1 | | Django Internal Tests: 500 Error |
2 | | No newline at end of file |