summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/core/handlers/base.py9
-rw-r--r--docs/releases/1.9.txt4
-rw-r--r--tests/handlers/templates/test_handler.html1
-rw-r--r--tests/handlers/tests_custom_error_handlers.py30
4 files changed, 44 insertions, 0 deletions
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index cad2ba2a60..04c8f79180 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -113,6 +113,9 @@ class BaseHandler(object):
urlconf = settings.ROOT_URLCONF
urlresolvers.set_urlconf(urlconf)
resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
+ # Use a flag to check if the response was rendered to prevent
+ # multiple renderings or to force rendering if necessary.
+ response_is_rendered = False
try:
response = None
# Apply request middleware
@@ -174,6 +177,7 @@ class BaseHandler(object):
"HttpResponse object. It returned None instead."
% (middleware_method.__self__.__class__.__name__))
response = response.render()
+ response_is_rendered = True
except http.Http404 as exc:
logger.warning('Not Found: %s', request.path,
@@ -246,6 +250,11 @@ class BaseHandler(object):
response._closable_objects.append(request)
+ # If the exception handler returns a TemplateResponse that has not
+ # been rendered, force it to be rendered.
+ if not response_is_rendered and callable(getattr(response, 'render', None)):
+ response = response.render()
+
return response
def handle_uncaught_exception(self, request, resolver, exc_info):
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 3aa6c495de..63e1335333 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -385,6 +385,10 @@ Requests and Responses
* The default 40x error views now accept a second positional parameter, the
exception that triggered the view.
+* View error handlers now support
+ :class:`~django.template.response.TemplateResponse`, commonly used with
+ class-based views.
+
Tests
^^^^^
diff --git a/tests/handlers/templates/test_handler.html b/tests/handlers/templates/test_handler.html
new file mode 100644
index 0000000000..6f46e3e88f
--- /dev/null
+++ b/tests/handlers/templates/test_handler.html
@@ -0,0 +1 @@
+Error handler content
diff --git a/tests/handlers/tests_custom_error_handlers.py b/tests/handlers/tests_custom_error_handlers.py
new file mode 100644
index 0000000000..24c2c8b446
--- /dev/null
+++ b/tests/handlers/tests_custom_error_handlers.py
@@ -0,0 +1,30 @@
+from django.conf.urls import url
+from django.core.exceptions import PermissionDenied
+from django.template.response import TemplateResponse
+from django.test import SimpleTestCase, override_settings
+
+
+def template_response_error_handler(request, exception=None):
+ return TemplateResponse(request, 'test_handler.html', status=403)
+
+
+def permission_denied_view(request):
+ raise PermissionDenied
+
+
+urlpatterns = [
+ url(r'^$', permission_denied_view),
+]
+
+handler403 = template_response_error_handler
+
+
+@override_settings(ROOT_URLCONF='handlers.tests_custom_error_handlers')
+class CustomErrorHandlerTests(SimpleTestCase):
+
+ def test_handler_renders_template_response(self):
+ """
+ BaseHandler should render TemplateResponse if necessary.
+ """
+ response = self.client.get('/')
+ self.assertContains(response, 'Error handler content', status_code=403)