Code

Ticket #16004: 16004.fix.alternative.2.diff

File 16004.fix.alternative.2.diff, 6.2 KB (added by lukeplant, 3 years ago)

Fixed issue found by Carl Meyer

Line 
1diff -r a05dd7353335 django/core/handlers/base.py
2--- a/django/core/handlers/base.py      Mon May 23 16:08:45 2011 +0000
3+++ b/django/core/handlers/base.py      Mon May 23 22:40:09 2011 +0100
4@@ -133,7 +133,7 @@
5                 if hasattr(response, 'render') and callable(response.render):
6                     for middleware_method in self._template_response_middleware:
7                         response = middleware_method(request, response)
8-                    response.render()
9+                    response = response.render()
10 
11             except http.Http404, e:
12                 logger.warning('Not Found: %s' % request.path,
13diff -r a05dd7353335 django/template/response.py
14--- a/django/template/response.py       Mon May 23 16:08:45 2011 +0000
15+++ b/django/template/response.py       Mon May 23 22:40:09 2011 +0100
16@@ -92,11 +92,14 @@
17 
18         Returns the baked response instance.
19         """
20+        retval = self
21         if not self._is_rendered:
22             self._set_content(self.rendered_content)
23             for post_callback in self._post_render_callbacks:
24-                post_callback(self)
25-        return self
26+                newretval = post_callback(retval)
27+                if newretval is not None:
28+                    retval = newretval
29+        return retval
30 
31     is_rendered = property(lambda self: self._is_rendered)
32 
33diff -r a05dd7353335 django/utils/decorators.py
34--- a/django/utils/decorators.py        Mon May 23 16:08:45 2011 +0000
35+++ b/django/utils/decorators.py        Mon May 23 22:40:09 2011 +0100
36@@ -95,10 +95,17 @@
37                         if result is not None:
38                             return result
39                     raise
40-                if hasattr(middleware, 'process_response'):
41-                    result = middleware.process_response(request, response)
42-                    if result is not None:
43-                        return result
44+                if hasattr(response, 'render') and callable(response.render):
45+                    if hasattr(middleware, 'process_template_response'):
46+                        response = middleware.process_template_response(request, response)
47+                    # Defer running of process_response, so that we don't
48+                    # force the template to be rendered just yet.
49+                    if hasattr(middleware, 'process_response'):
50+                        callback = lambda response: middleware.process_response(request, response)
51+                        response.add_post_render_callback(callback)
52+                else:
53+                    if hasattr(middleware, 'process_response'):
54+                        return middleware.process_response(request, response)
55                 return response
56             return _wrapped_view
57         return _decorator
58diff -r a05dd7353335 docs/ref/template-response.txt
59--- a/docs/ref/template-response.txt    Mon May 23 16:08:45 2011 +0000
60+++ b/docs/ref/template-response.txt    Mon May 23 22:40:09 2011 +0100
61@@ -119,6 +119,10 @@
62     rendered :class:`~django.template.response.SimpleTemplateResponse`
63     instance.
64 
65+    If the callback returns a value that is not `None`, this will be
66+    used as the response instead of the original response object (and
67+    will be passed to the next post rendering callback etc.)
68+
69 .. method:: SimpleTemplateResponse.render():
70 
71     Sets :attr:`response.content` to the result obtained by
72diff -r a05dd7353335 tests/regressiontests/utils/decorators.py
73--- a/tests/regressiontests/utils/decorators.py Mon May 23 16:08:45 2011 +0000
74+++ b/tests/regressiontests/utils/decorators.py Mon May 23 22:40:09 2011 +0100
75@@ -1,5 +1,7 @@
76 from django.http import HttpResponse
77 from django.middleware.doc import XViewMiddleware
78+from django.template import Template, Context
79+from django.template.response import TemplateResponse
80 from django.test import TestCase, RequestFactory
81 from django.utils.decorators import decorator_from_middleware
82 
83@@ -19,6 +21,38 @@
84 class_xview = xview_dec(ClassXView())
85 
86 
87+class FullMiddleware(object):
88+    def process_request(self, request):
89+        request.process_request_reached = True
90+
91+    def process_view(sef, request, view_func, view_args, view_kwargs):
92+        request.process_view_reached = True
93+
94+    def process_template_response(self, request, response):
95+        request.process_template_response_reached = True
96+        return response
97+
98+    def process_response(self, request, response):
99+        # This should never receive unrendered content.
100+        request.process_response_content = response.content
101+        request.process_response_reached = True
102+        return response
103+
104+full_dec = decorator_from_middleware(FullMiddleware)
105+
106+
107+def template_response_view(request):
108+    t = Template("Hello world")
109+    return TemplateResponse(request, t, {})
110+
111+decorated_template_response_view = full_dec(template_response_view)
112+
113+def normal_view(request):
114+    t = Template("Hello world")
115+    return HttpResponse(t.render(Context({})))
116+
117+decorated_view = full_dec(normal_view)
118+
119 class DecoratorFromMiddlewareTests(TestCase):
120     """
121     Tests for view decorators created using
122@@ -37,3 +71,24 @@
123         Test a middleware that implements process_view, operating on a callable class.
124         """
125         class_xview(self.rf.get('/'))
126+
127+    def test_full_middleware_dec_normal(self):
128+        # Combined tests for all methods are easier
129+        request = self.rf.get('/')
130+        response = decorated_view(request)
131+        self.assertTrue(request.process_request_reached)
132+        self.assertTrue(request.process_view_reached)
133+        self.assertTrue(request.process_response_reached)
134+        self.assertEqual(request.process_response_content, "Hello world")
135+
136+    def test_full_middleware_dec_templateresponse(self):
137+        # Combined tests for all methods are easier
138+        request = self.rf.get('/')
139+        response = decorated_template_response_view(request)
140+        self.assertFalse(response._is_rendered)
141+        response.render()
142+        self.assertTrue(request.process_request_reached)
143+        self.assertTrue(request.process_view_reached)
144+        self.assertTrue(request.process_template_response_reached)
145+        self.assertTrue(request.process_response_reached)
146+        self.assertEqual(request.process_response_content, "Hello world")