diff -r 128c90a7b280 django/template/response.py
--- a/django/template/response.py	Mon May 23 13:17:08 2011 +0100
+++ b/django/template/response.py	Mon May 23 17:07:17 2011 +0100
@@ -92,11 +92,14 @@
 
         Returns the baked response instance.
         """
+        retval = self
         if not self._is_rendered:
             self._set_content(self.rendered_content)
             for post_callback in self._post_render_callbacks:
-                post_callback(self)
-        return self
+                newretval = post_callback(retval)
+                if newretval is not None:
+                    retval = newretval
+        return retval
 
     is_rendered = property(lambda self: self._is_rendered)
 
diff -r 128c90a7b280 django/utils/decorators.py
--- a/django/utils/decorators.py	Mon May 23 13:17:08 2011 +0100
+++ b/django/utils/decorators.py	Mon May 23 17:07:17 2011 +0100
@@ -95,10 +95,17 @@
                         if result is not None:
                             return result
                     raise
-                if hasattr(middleware, 'process_response'):
-                    result = middleware.process_response(request, response)
-                    if result is not None:
-                        return result
+                if hasattr(response, 'render') and callable(response.render):
+                    if hasattr(middleware, 'process_template_response'):
+                        response = middleware.process_template_response(request, response)
+                    # Defer running of process_response, so that we don't
+                    # force the template to be rendered just yet.
+                    if hasattr(middleware, 'process_response'):
+                        callback = lambda response: middleware.process_response(request, response)
+                        response.add_post_render_callback(callback)
+                else:
+                    if hasattr(middleware, 'process_response'):
+                        return middleware.process_response(request, response)
                 return response
             return _wrapped_view
         return _decorator
diff -r 128c90a7b280 docs/ref/template-response.txt
--- a/docs/ref/template-response.txt	Mon May 23 13:17:08 2011 +0100
+++ b/docs/ref/template-response.txt	Mon May 23 17:07:17 2011 +0100
@@ -119,6 +119,10 @@
     rendered :class:`~django.template.response.SimpleTemplateResponse`
     instance.
 
+    If the callback returns a value that is not `None`, this will be
+    used as the response instead of the original response object (and
+    will be passed to the next post rendering callback etc.)
+
 .. method:: SimpleTemplateResponse.render():
 
     Sets :attr:`response.content` to the result obtained by
diff -r 128c90a7b280 tests/regressiontests/utils/decorators.py
--- a/tests/regressiontests/utils/decorators.py	Mon May 23 13:17:08 2011 +0100
+++ b/tests/regressiontests/utils/decorators.py	Mon May 23 17:07:17 2011 +0100
@@ -1,5 +1,7 @@
 from django.http import HttpResponse
 from django.middleware.doc import XViewMiddleware
+from django.template import Template, Context
+from django.template.response import TemplateResponse
 from django.test import TestCase, RequestFactory
 from django.utils.decorators import decorator_from_middleware
 
@@ -19,6 +21,38 @@
 class_xview = xview_dec(ClassXView())
 
 
+class FullMiddleware(object):
+    def process_request(self, request):
+        request.process_request_reached = True
+
+    def process_view(sef, request, view_func, view_args, view_kwargs):
+        request.process_view_reached = True
+
+    def process_template_response(self, request, response):
+        request.process_template_response_reached = True
+        return response
+
+    def process_response(self, request, response):
+        # This should never receive unrendered content.
+        request.process_response_content = response.content
+        request.process_response_reached = True
+        return response
+
+full_dec = decorator_from_middleware(FullMiddleware)
+
+
+def template_response_view(request):
+    t = Template("Hello world")
+    return TemplateResponse(request, t, {})
+
+decorated_template_response_view = full_dec(template_response_view)
+
+def normal_view(request):
+    t = Template("Hello world")
+    return HttpResponse(t.render(Context({})))
+
+decorated_view = full_dec(normal_view)
+
 class DecoratorFromMiddlewareTests(TestCase):
     """
     Tests for view decorators created using
@@ -37,3 +71,24 @@
         Test a middleware that implements process_view, operating on a callable class.
         """
         class_xview(self.rf.get('/'))
+
+    def test_full_middleware_dec_normal(self):
+        # Combined tests for all methods are easier
+        request = self.rf.get('/')
+        response = decorated_view(request)
+        self.assertTrue(request.process_request_reached)
+        self.assertTrue(request.process_view_reached)
+        self.assertTrue(request.process_response_reached)
+        self.assertEqual(request.process_response_content, "Hello world")
+
+    def test_full_middleware_dec_templateresponse(self):
+        # Combined tests for all methods are easier
+        request = self.rf.get('/')
+        response = decorated_template_response_view(request)
+        self.assertFalse(response._is_rendered)
+        response.render()
+        self.assertTrue(request.process_request_reached)
+        self.assertTrue(request.process_view_reached)
+        self.assertTrue(request.process_template_response_reached)
+        self.assertTrue(request.process_response_reached)
+        self.assertEqual(request.process_response_content, "Hello world")
