2
0
Эх сурвалжийг харах

Fixed #24829 -- Allowed use of TemplateResponse in view error handlers.

ana-balica 9 жил өмнө
parent
commit
2f615b10e6

+ 9 - 0
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):

+ 4 - 0
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
 ^^^^^
 

+ 1 - 0
tests/handlers/templates/test_handler.html

@@ -0,0 +1 @@
+Error handler content

+ 30 - 0
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)