diff -r 78ad3faa689b django/contrib/messages/middleware.py
--- a/django/contrib/messages/middleware.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/contrib/messages/middleware.py	Sun Nov 28 14:50:46 2010 +0800
@@ -1,7 +1,6 @@
 from django.conf import settings
 from django.contrib.messages.storage import default_storage
 
-
 class MessageMiddleware(object):
     """
     Middleware that handles temporary messages.
diff -r 78ad3faa689b django/contrib/messages/tests/base.py
--- a/django/contrib/messages/tests/base.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/contrib/messages/tests/base.py	Sun Nov 28 14:50:46 2010 +0800
@@ -103,7 +103,7 @@
         storage = self.get_storage()
         self.assertFalse(storage.added_new)
         storage.add(constants.INFO, 'Test message 1')
-        self.assert_(storage.added_new)
+        self.assertTrue(storage.added_new)
         storage.add(constants.INFO, 'Test message 2', extra_tags='tag')
         self.assertEqual(len(storage), 2)
 
@@ -180,6 +180,26 @@
             for msg in data['messages']:
                 self.assertContains(response, msg)
 
+    def test_with_template_response(self):
+        settings.MESSAGE_LEVEL = constants.DEBUG
+        data = {
+            'messages': ['Test message %d' % x for x in xrange(10)],
+        }
+        show_url = reverse('django.contrib.messages.tests.urls.show_template_response')
+        for level in self.levels.keys():
+            add_url = reverse('django.contrib.messages.tests.urls.add_template_response',
+                              args=(level,))
+            response = self.client.post(add_url, data, follow=True)
+            self.assertRedirects(response, show_url)
+            self.assertTrue('messages' in response.context)
+            for msg in data['messages']:
+                self.assertContains(response, msg)
+
+            # there shouldn't be any messages on second GET request
+            response = self.client.get(show_url)
+            for msg in data['messages']:
+                self.assertNotContains(response, msg)
+
     def test_multiple_posts(self):
         """
         Tests that messages persist properly when multiple POSTs are made
diff -r 78ad3faa689b django/contrib/messages/tests/urls.py
--- a/django/contrib/messages/tests/urls.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/contrib/messages/tests/urls.py	Sun Nov 28 14:50:46 2010 +0800
@@ -2,9 +2,20 @@
 from django.contrib import messages
 from django.core.urlresolvers import reverse
 from django.http import HttpResponseRedirect, HttpResponse
-from django.shortcuts import render_to_response
+from django.shortcuts import render_to_response, redirect
 from django.template import RequestContext, Template
+from django.template.response import TemplateResponse
 
+TEMPLATE = """{% if messages %}
+<ul class="messages">
+    {% for message in messages %}
+    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
+        {{ message }}
+    </li>
+    {% endfor %}
+</ul>
+{% endif %}
+"""
 
 def add(request, message_type):
     # don't default to False here, because we want to test that it defaults
@@ -16,24 +27,27 @@
                                             fail_silently=fail_silently)
         else:
             getattr(messages, message_type)(request, msg)
+
     show_url = reverse('django.contrib.messages.tests.urls.show')
     return HttpResponseRedirect(show_url)
 
+def add_template_response(request, message_type):
+    for msg in request.POST.getlist('messages'):
+        getattr(messages, message_type)(request, msg)
+
+    show_url = reverse('django.contrib.messages.tests.urls.show_template_response')
+    return HttpResponseRedirect(show_url)
 
 def show(request):
-    t = Template("""{% if messages %}
-<ul class="messages">
-    {% for message in messages %}
-    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
-        {{ message }}
-    </li>
-    {% endfor %}
-</ul>
-{% endif %}""")
+    t = Template(TEMPLATE)
     return HttpResponse(t.render(RequestContext(request)))
 
+def show_template_response(request):
+    return TemplateResponse(request, Template(TEMPLATE))
 
 urlpatterns = patterns('',
     ('^add/(debug|info|success|warning|error)/$', add),
     ('^show/$', show),
+    ('^template_response/add/(debug|info|success|warning|error)/$', add_template_response),
+    ('^template_response/show/$', show_template_response),
 )
diff -r 78ad3faa689b django/core/handlers/base.py
--- a/django/core/handlers/base.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/core/handlers/base.py	Sun Nov 28 14:50:46 2010 +0800
@@ -21,6 +21,7 @@
     def __init__(self):
         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
 
+
     def load_middleware(self):
         """
         Populate middleware lists from settings.MIDDLEWARE_CLASSES.
@@ -30,27 +31,14 @@
         from django.conf import settings
         from django.core import exceptions
         self._view_middleware = []
+        self._template_response_middleware = []
         self._response_middleware = []
         self._exception_middleware = []
 
         request_middleware = []
         for middleware_path in settings.MIDDLEWARE_CLASSES:
             try:
-                dot = middleware_path.rindex('.')
-            except ValueError:
-                raise exceptions.ImproperlyConfigured('%s isn\'t a middleware module' % middleware_path)
-            mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
-            try:
-                mod = import_module(mw_module)
-            except ImportError, e:
-                raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
-            try:
-                mw_class = getattr(mod, mw_classname)
-            except AttributeError:
-                raise exceptions.ImproperlyConfigured('Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname))
-
-            try:
-                mw_instance = mw_class()
+                mw_instance = get_middleware_instance(middleware_path)
             except exceptions.MiddlewareNotUsed:
                 continue
 
@@ -58,6 +46,8 @@
                 request_middleware.append(mw_instance.process_request)
             if hasattr(mw_instance, 'process_view'):
                 self._view_middleware.append(mw_instance.process_view)
+            if hasattr(mw_instance, 'process_template_response'):
+                self._template_response_middleware.insert(0, mw_instance.process_template_response)
             if hasattr(mw_instance, 'process_response'):
                 self._response_middleware.insert(0, mw_instance.process_response)
             if hasattr(mw_instance, 'process_exception'):
@@ -164,6 +154,13 @@
             urlresolvers.set_urlconf(None)
 
         try:
+            # Apply template response middleware and the bake the response
+            # if the response can be baked
+            if hasattr(response, 'bake') and callable(response.bake):
+                for middleware_method in self._template_response_middleware:
+                    response = middleware_method(request, response)
+                response.bake()
+
             # Apply response middleware, regardless of the response
             for middleware_method in self._response_middleware:
                 response = middleware_method(request, response)
@@ -241,3 +238,22 @@
     if script_url:
         return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
     return force_unicode(environ.get('SCRIPT_NAME', u''))
+
+def get_middleware_instance(middleware_path):
+    """
+    Returns middleware instance
+    """
+    try:
+        mw_module, mw_classname = middleware_path.rsplit('.', 1)
+    except ValueError:
+        raise exceptions.ImproperlyConfigured('%s isn\'t a middleware module' % middleware_path)
+    try:
+        mod = import_module(mw_module)
+    except ImportError, e:
+        raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
+    try:
+        mw_class = getattr(mod, mw_classname)
+    except AttributeError:
+        raise exceptions.ImproperlyConfigured('Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname))
+
+    return mw_class()
diff -r 78ad3faa689b django/shortcuts/__init__.py
--- a/django/shortcuts/__init__.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/shortcuts/__init__.py	Sun Nov 28 14:50:46 2010 +0800
@@ -4,7 +4,7 @@
 for convenience's sake.
 """
 
-from django.template import loader
+from django.template import loader, RequestContext
 from django.http import HttpResponse, Http404
 from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
 from django.db.models.manager import Manager
@@ -19,20 +19,31 @@
     httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
     return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
 
+def render(request, *args, **kwargs):
+    """
+    Returns a HttpResponse whose content is filled with the result of calling
+    django.template.loader.render_to_string() with the passed arguments.
+    Uses a RequestContext by default.
+    """
+    httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
+    kwargs['context_instance'] = kwargs.get('context_instance', RequestContext(request))
+    return HttpResponse(loader.render_to_string(*args, **kwargs),
+                        **httpresponse_kwargs)
+
 def redirect(to, *args, **kwargs):
     """
     Returns an HttpResponseRedirect to the apropriate URL for the arguments
     passed.
-    
+
     The arguments could be:
-    
+
         * A model: the model's `get_absolute_url()` function will be called.
-    
+
         * A view name, possibly with arguments: `urlresolvers.reverse()` will
           be used to reverse-resolve the name.
-         
+
         * A URL, which will be used as-is for the redirect location.
-        
+
     By default issues a temporary redirect; pass permanent=True to issue a
     permanent redirect
     """
@@ -40,11 +51,11 @@
         redirect_class = HttpResponsePermanentRedirect
     else:
         redirect_class = HttpResponseRedirect
-    
+
     # If it's a model, use get_absolute_url()
     if hasattr(to, 'get_absolute_url'):
         return redirect_class(to.get_absolute_url())
-    
+
     # Next try a reverse URL resolution.
     try:
         return redirect_class(urlresolvers.reverse(to, args=args, kwargs=kwargs))
@@ -55,7 +66,7 @@
         # If this doesn't "feel" like a URL, re-raise.
         if '/' not in to and '.' not in to:
             raise
-        
+
     # Finally, fall back and assume it's a URL
     return redirect_class(to)
 
@@ -101,4 +112,5 @@
     obj_list = list(queryset.filter(*args, **kwargs))
     if not obj_list:
         raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
-    return obj_list
\ No newline at end of file
+    return obj_list
+
diff -r 78ad3faa689b django/template/response.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/django/template/response.py	Sun Nov 28 14:50:46 2010 +0800
@@ -0,0 +1,109 @@
+from django.http import HttpResponse
+from django.template import loader, Context, RequestContext
+
+class ContentNotBakedError(Exception):
+    pass
+
+class SimpleTemplateResponse(HttpResponse):
+
+    def __init__(self, template, context=None, mimetype=None, status=None,
+            content_type=None):
+        # It would seem obvious to call these next two members 'template' and
+        # 'context', but those names are reserved as part of the test Client API.
+        # To avoid the name collision, we use
+        # tricky-to-debug problems
+        self.template_name = template
+        self.context_data = context
+
+        # _baked tracks whether the template and context has been baked into
+        # a final response.
+        self._baked = False
+
+        # content argument doesn't make sense here because it will be replaced
+        # with rendered template so we always pass empty string in order to
+        # prevent errors and provide shorter signature.
+        super(SimpleTemplateResponse, self).__init__('', mimetype, status,
+                                                     content_type)
+
+    def resolve_template(self, template):
+        "Accepts a template object, path-to-template or list of paths"
+        if isinstance(template, (list, tuple)):
+            return loader.select_template(template)
+        elif isinstance(template, basestring):
+            return loader.get_template(template)
+        else:
+            return template
+
+    def resolve_context(self, context):
+        """Convert context data into a full Context object
+        (assuming it isn't already a Context object).
+        """
+        if isinstance(context, Context):
+            return context
+        else:
+            return Context(context)
+
+    def render(self):
+        "Render the content of the response. Returns the rendered content"
+        template = self.resolve_template(self.template_name)
+        context = self.resolve_context(self.context_data)
+        content = template.render(context)
+        return content
+
+    def bake(self):
+        """Bake the response.
+
+        If the content has already been baked, this is a no-op.
+
+        Returns the baked response instance.
+        """
+        if not self._baked:
+            self._set_content(self.render())
+        return self
+
+    baked = property(lambda self: self._baked)
+
+    def __iter__(self):
+        if not self._baked:
+            raise ContentNotBakedError('The response content must be baked before it can be iterated over.')
+        return super(SimpleTemplateResponse, self).__iter__()
+
+    def _get_content(self):
+        if not self._baked:
+            raise ContentNotBakedError('The response content must be baked before it can be accessed.')
+        return super(SimpleTemplateResponse, self)._get_content()
+
+    def _set_content(self, value):
+        "Overrides rendered content, unless you later call bake()"
+        super(SimpleTemplateResponse, self)._set_content(value)
+        self._baked = True
+
+    content = property(_get_content, _set_content)
+
+class TemplateResponse(SimpleTemplateResponse):
+
+    def __init__(self, request, template, context=None, mimetype=None,
+            status=None, content_type=None):
+        # self.request gets over-written by django.test.client.Client - and
+        # unlike context_data and template_name the _request should not
+        # be considered part of the public API.
+        self._request = request
+        super(TemplateResponse, self).__init__(
+            template, context, mimetype, status, content_type)
+
+    def resolve_context(self, context):
+        """Convert context data into a full RequestContext object
+        (assuming it isn't already a Context object).
+        """
+        if isinstance(context, Context):
+            return context
+        else:
+            return RequestContext(self._request, context)
+
+def bake(response):
+    """
+    Bakes response if it can be baked. Unbakeable instances (such as
+    normal HttpResponse instances) are unaffected.
+    """
+    if (hasattr(response, 'bake') and callable(response.bake)):
+        response.bake()
diff -r 78ad3faa689b django/views/generic/base.py
--- a/django/views/generic/base.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/django/views/generic/base.py	Sun Nov 28 14:50:46 2010 +0800
@@ -1,6 +1,7 @@
 from django import http
 from django.core.exceptions import ImproperlyConfigured
 from django.template import RequestContext, loader
+from django.template.response import TemplateResponse
 from django.utils.functional import update_wrapper
 from django.utils.log import getLogger
 from django.utils.decorators import classonlymethod
@@ -81,59 +82,29 @@
     A mixin that can be used to render a template.
     """
     template_name = None
+    response_class = TemplateResponse
 
-    def render_to_response(self, context):
+    def render_to_response(self, context, **response_kwargs):
         """
         Returns a response with a template rendered with the given context.
         """
-        return self.get_response(self.render_template(context))
-
-    def get_response(self, content, **httpresponse_kwargs):
-        """
-        Construct an `HttpResponse` object.
-        """
-        return http.HttpResponse(content, **httpresponse_kwargs)
-
-    def render_template(self, context):
-        """
-        Render the template with a given context.
-        """
-        context_instance = self.get_context_instance(context)
-        return self.get_template().render(context_instance)
-
-    def get_context_instance(self, context):
-        """
-        Get the template context instance. Must return a Context (or subclass)
-        instance.
-        """
-        return RequestContext(self.request, context)
-
-    def get_template(self):
-        """
-        Get a ``Template`` object for the given request.
-        """
-        names = self.get_template_names()
-        if not names:
-            raise ImproperlyConfigured(u"'%s' must provide template_name."
-                                       % self.__class__.__name__)
-        return self.load_template(names)
+        return self.response_class(
+            request = self.request,
+            template = self.get_template_names(),
+            context = context,
+            **response_kwargs
+        )
 
     def get_template_names(self):
         """
-        Return a list of template names to be used for the request. Must return
-        a list. May not be called if get_template is overridden.
+        Returns a list of template names to be used for the request. Must return
+        a list. May not be called if render_to_response is overridden.
         """
         if self.template_name is None:
             return []
         else:
             return [self.template_name]
 
-    def load_template(self, names):
-        """
-        Load a list of templates using the default template loader.
-        """
-        return loader.select_template(names)
-
 
 class TemplateView(TemplateResponseMixin, View):
     """
diff -r 78ad3faa689b docs/index.txt
--- a/docs/index.txt	Sat Nov 27 05:47:30 2010 +0000
+++ b/docs/index.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -93,7 +93,9 @@
       :doc:`View functions <topics/http/views>` |
       :doc:`Shortcuts <topics/http/shortcuts>`
 
-    * **Reference:**  :doc:`Request/response objects <ref/request-response>`
+    * **Reference:**
+      :doc:`Request/response objects <ref/request-response>` |
+      :doc:`TemplateResponse objects <ref/template-response>`
 
     * **File uploads:**
       :doc:`Overview <topics/http/file-uploads>` |
diff -r 78ad3faa689b docs/ref/class-based-views.txt
--- a/docs/ref/class-based-views.txt	Sat Nov 27 05:47:30 2010 +0000
+++ b/docs/ref/class-based-views.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -76,39 +76,25 @@
 
         The path to the template to use when rendering the view.
 
-    .. method:: render_to_response(context)
+    .. attribute:: response_class
 
-        Returns a full composed HttpResponse instance, ready to be returned to
-        the user.
+        The response class to be returned by ``render_to_response`` method.
+        Default is
+        :class:`TemplateResponse <django.template.response.TemplateResponse>`.
+        The template and context of TemplateResponse instances can be
+        altered later (e.g. in
+        :ref:`template response middleware <template-response-middleware>`).
 
-        Calls :meth:`~TemplateResponseMixin.render_template()` to build the
-        content of the response, and
-        :meth:`~TemplateResponseMixin.get_response()` to construct the
-        :class:`~django.http.HttpResponse` object.
+        Create TemplateResponse subclass and pass set it to
+        ``template_response_class`` if you need custom template loading or
+        custom context object instantiation.
 
-    .. method:: get_response(content, **httpresponse_kwargs)
+    .. method:: render_to_response(context, **response_kwargs)
 
-        Constructs the :class:`~django.http.HttpResponse` object around the
-        given content. If any keyword arguments are provided, they will be
-        passed to the constructor of the :class:`~django.http.HttpResponse`
-        instance.
+        Returns a ``self.template_response_class`` instance.
 
-    .. method:: render_template(context)
-
-        Calls :meth:`~TemplateResponseMixin.get_context_instance()` to obtain
-        the :class:`Context` instance to use for rendering, and calls
-        :meth:`TemplateReponseMixin.get_template()` to load the template that
-        will be used to render the final content.
-
-    .. method:: get_context_instance(context)
-
-        Turns the data dictionary ``context`` into an actual context instance
-        that can be used for rendering.
-
-        By default, constructs a :class:`~django.template.RequestContext`
-        instance.
-
-    .. method:: get_template()
+        If any keyword arguments are provided, they will be
+        passed to the constructor of the response instance.
 
         Calls :meth:`~TemplateResponseMixin.get_template_names()` to obtain the
         list of template names that will be searched looking for an existent
@@ -123,10 +109,6 @@
         default implementation will return a list containing
         :attr:`TemplateResponseMixin.template_name` (if it is specified).
 
-    .. method:: load_template(names)
-
-        Loads and returns a template found by searching the list of ``names``
-        for a match. Uses Django's default template loader.
 
 Single object mixins
 --------------------
diff -r 78ad3faa689b docs/ref/index.txt
--- a/docs/ref/index.txt	Sat Nov 27 05:47:30 2010 +0000
+++ b/docs/ref/index.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -16,6 +16,7 @@
    middleware
    models/index
    request-response
+   template-response
    settings
    signals
    templates/index
diff -r 78ad3faa689b docs/ref/template-response.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/ref/template-response.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -0,0 +1,201 @@
+===========================================
+TemplateResponse and SimpleTemplateResponse
+===========================================
+
+.. versionadded:: 1.3
+
+.. module:: django.template.response
+   :synopsis: Classes dealing with lazy-rendered HTTP responses.
+
+Standard HttpResponse objects are static structures. They are provided
+with a block of pre-rendered content at time of construction, and
+while that content can be modified, it isn't in a form that makes it
+easy to perform modifications.
+
+However, it can sometimes be beneficial to allow decorators or
+middleware to modify a response *after* it has been constructed by the
+view. For example, you may want to change the template that is used,
+or put additional data into the context.
+
+TemplateResponse provides a way to do just that. Unlike basic
+HttpResponse objects, TemplateResponse objects retain the details of
+the template and context that was provided by the view to compute the
+response. The final output of the response is not computed until
+it is needed.
+
+TemplateResponse objects
+========================
+
+.. class:: SimpleTemplateResponse()
+
+Attributes
+----------
+
+.. attribute:: SimpleTemplateResponse.template_name
+
+    The name of the template to be rendered. Accepts
+    :class:`django.template.Template` object, path to template or list
+    of paths.
+
+    Example: ``['foo.html', 'path/to/bar.html']``
+
+.. attribute:: SimpleTemplateResponse.context_data
+
+    The context data to be used when rendering the template. It can be
+    a dictionary or a context object.
+
+    Example: ``{'foo': 123}``
+
+
+Methods
+-------
+
+.. method:: SimpleTemplateResponse.__init__(template, context=None, mimetype=None, status=None, content_type=None)
+
+    Instantiates an
+    :class:`~django.template.response.SimpleTemplateResponse` object
+    with the given template, context, MIME type and HTTP status.
+
+    ``template`` is a full name of a template, or a sequence of
+    template names. :class:`django.template.Template` instances can also be used.
+
+    ``context`` is a dictionary of values to add to the template context.
+    By default, this is an empty dictionary. :class:`~django.template.Context` objects are also
+    accepted as ``context`` values.
+
+    ``status`` is the HTTP Status code for the response.
+
+    ``content_type`` is an alias for ``mimetype``. Historically, this parameter
+    was only called ``mimetype``, but since this is actually the value included
+    in the HTTP ``Content-Type`` header, it can also include the character set
+    encoding, which makes it more than just a MIME type specification.
+    If ``mimetype`` is specified (not ``None``), that value is used.
+    Otherwise, ``content_type`` is used. If neither is given, the
+    ``DEFAULT_CONTENT_TYPE`` setting is used.
+
+
+.. method:: SimpleTemplateResponse.resolve_context(context)
+
+    Converts context data into a context instance that can be used for
+    rendering a template. Accepts a dictionary of context data or a
+    context object. Returns a :class:`~django.template.Context`
+    instance containing the provided data.
+
+    Override this method in order to customize context instantiation.
+
+.. method:: SimpleTemplateResponse.resolve_template(template)
+
+    Resolves the template instance to use for rendering. Accepts a
+    path of a template to use, or a sequence of template paths.
+    :class:`~django.template.Template` instances may also be provided.
+    Returns the :class:`~django.template.Template` instance to be
+    rendered.
+
+    Override this method in order to customize template rendering.
+
+.. method:: SimpleTemplateResponse.render():
+
+    Renders a template instance returned by
+    :meth:`SimpleTemplateResponse.resolve_template` using the context instance
+    returned by :meth:`SimpleTemplateResponse.resolve_context` and returns the
+    rendered content.
+
+.. method:: SimpleTemplateResponse.bake():
+
+    Bakes the response by setting :attr:`response.content` to the result
+    returned by :meth:`SimpleTemplateResponse.render`.
+
+    The response is baked by Django during response middleware cycle. You should
+    only bake the response yourself if it is to be used outside the
+    request-response cycle (e.g. for debugging). It will be baked twice
+    otherwise.
+
+
+.. class:: TemplateResponse()
+
+   TemplateResponse is a subclass of
+   :class:`SimpleTemplateResponse <django.template.response.SimpleTemplateResponse>`
+   that uses RequestContext instead of Context.
+
+.. method:: TemplateResponse.__init__(request, template, context=None, mimetype=None, status=None, content_type=None)
+
+   Instantiates an ``TemplateResponse`` object with the given template,
+   context, MIME type and HTTP status.
+
+   ``request`` is a HttpRequest instance.
+
+   ``template`` is a full name of a template to use or sequence of
+   template names. :class:`django.template.Template` instances are also
+   accepted.
+
+   ``context`` is a dictionary of values to add to the template context.
+   By default, this is an empty dictionary; context objects are also accepted
+   as ``context`` values.
+
+   ``status`` is the HTTP Status code for the response.
+
+   ``content_type`` is an alias for ``mimetype``. Historically, this parameter
+   was only called ``mimetype``, but since this is actually the value included
+   in the HTTP ``Content-Type`` header, it can also include the character set
+   encoding, which makes it more than just a MIME type specification.
+   If ``mimetype`` is specified (not ``None``), that value is used.
+   Otherwise, ``content_type`` is used. If neither is given, the
+   ``DEFAULT_CONTENT_TYPE`` setting is used.
+
+
+Baking
+======
+
+*Baking* is the process by which the content in a TemplateResponse is
+converted into the final form that will be returned to the client.
+
+There are three circumstances under which a TemplateResponse is baked:
+
+    * When the TemplateResponse instance is explicitly baked, using
+      the :meth:`bake()` method.
+
+    * When the content of the response is explicitly set by assigning
+      :attr:`response.content`.
+
+    * After passing through template response middleware, but before
+      passing through response middleware.
+
+A TemplateResponse can only be baked once. The first call to
+:meth:`bake()` sets the content of the response; subsequent baking
+calls do not change the response content.
+
+However, when :attr:`response.content` is explicitly assigned, the
+change is always applied. If you want to force templated content to be
+rebaked, you can re-render the content and assign it::
+
+    # Set up a baked TemplateResponse
+    >>> t = TemplateResponse(request, 'original.html', {})
+    >>> t.bake()
+    >>> print t.content
+    Original content
+
+    # Rebaking doesn't change content
+    >>> t.template_name = 'other.html'
+    >>> t.bake()
+    >>> print t.content
+    Original content
+
+    # Assigning content does change
+    >>> t.content = t.render()
+    >>> print t.content
+    Other content
+
+Using TemplateResponse and SimpleTemplateResponse
+=================================================
+
+A TemplateResponse object can be used anywhere that a normal
+HttpResponse can be used. It can also be used as an alternative to
+calling render_to_response().
+
+For example, the following simple view returns a TemplateResponse
+with a simple template, and a context containing a queryset::
+
+    from django.template.response import TemplateResponse
+
+    def blog_index(request):
+        return TemplateResponse(request, 'entry_list.html', {'entries': Entry.objects.all()})
diff -r 78ad3faa689b docs/topics/http/middleware.txt
--- a/docs/topics/http/middleware.txt	Sat Nov 27 05:47:30 2010 +0000
+++ b/docs/topics/http/middleware.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -120,6 +120,37 @@
 classes are applied in reverse order, from the bottom up. This means classes
 defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first.
 
+.. _template-response-middleware:
+
+``process_template_response``
+-----------------------------
+
+.. versionadded:: 1.3
+
+.. method:: process_template_response(self, request, response)
+
+``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the
+:class:`~django.template.response.SimpleTemplateResponse` subclass (e.g.
+:class:`~django.template.response.TemplateResponse`) object returned by a
+Django view.
+
+``process_template_response()`` must return an
+:class:`~django.template.response.SimpleTemplateResponse` (or it's subclass)
+object. It could alter the given ``response`` by changing
+``response.template_name`` and ``response.template_context``, or it could
+create and return a brand-new
+:class:`~django.template.response.SimpleTemplateResponse` (or it's subclass)
+instance.
+
+``process_template_response()`` is only called on response instances that
+can be baked. It is called before the ``process_response()`` method.
+
+You don't need to explicitly bake responses -- responses will be automatically baked
+once all template response middleware has been called.
+
+Middleware are run in reverse order during the response phase, which
+includes process_template_response.
+
 .. _exception-middleware:
 
 ``process_exception``
@@ -137,7 +168,7 @@
 the browser. Otherwise, default exception handling kicks in.
 
 Again, middleware are run in reverse order during the response phase, which
-includes ``process_exception``. If an exception middleware return a response,
+includes ``process_exception``. If an exception middleware returns a response,
 the middleware classes above that middleware will not be called at all.
 
 ``__init__``
diff -r 78ad3faa689b docs/topics/http/shortcuts.txt
--- a/docs/topics/http/shortcuts.txt	Sat Nov 27 05:47:30 2010 +0000
+++ b/docs/topics/http/shortcuts.txt	Sun Nov 28 14:50:46 2010 +0800
@@ -12,6 +12,70 @@
 "span" multiple levels of MVC. In other words, these functions/classes
 introduce controlled coupling for convenience's sake.
 
+``render``
+==========
+
+.. function:: render(request, template[, dictionary][, context_instance][, mimetype])
+
+   Combines a given template with a given context dictionary and returns an
+   :class:`~django.http.HttpResponse` object with that rendered text.
+
+   :func:`render()` is the same as a call to
+   :func:`render_to_response()` with a context_instance argument that
+   that forces the use of a :class:`RequestContext`.
+
+Required arguments
+------------------
+
+``request``
+    The request object used to generate this response.
+
+``template``
+    The full name of a template to use or sequence of template names.
+
+Optional arguments
+------------------
+
+``dictionary``
+    A dictionary of values to add to the template context. By default, this
+    is an empty dictionary. If a value in the dictionary is callable, the
+    view will call it just before rendering the template.
+
+``context_instance``
+    The context instance to render the template with. By default, the template
+    will be rendered with a ``RequestContext`` instance (filled with values from
+    ``request`` and ```dictionary``).
+
+``mimetype``
+    The MIME type to use for the resulting document. Defaults to the value of
+    the :setting:`DEFAULT_CONTENT_TYPE` setting.
+
+Example
+-------
+
+The following example renders the template ``myapp/index.html`` with the
+MIME type ``application/xhtml+xml``::
+
+    from django.shortcuts import render_to_response
+
+    def my_view(request):
+        # View code here...
+        return render_to_response('myapp/index.html', {"foo": "bar"},
+            mimetype="application/xhtml+xml")
+
+This example is equivalent to::
+
+    from django.http import HttpResponse
+    from django.template import Context, loader
+
+    def my_view(request):
+        # View code here...
+        t = loader.get_template('myapp/template.html')
+        c = RequestContext(request, {'foo': 'bar'})
+        return HttpResponse(t.render(c),
+            mimetype="application/xhtml+xml")
+
+
 ``render_to_response``
 ======================
 
diff -r 78ad3faa689b tests/regressiontests/generic_views/base.py
--- a/tests/regressiontests/generic_views/base.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/generic_views/base.py	Sun Nov 28 14:50:46 2010 +0800
@@ -156,6 +156,7 @@
     rf = RequestFactory()
 
     def _assert_about(self, response):
+        response.bake()
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.content, '<h1>About</h1>')
 
diff -r 78ad3faa689b tests/regressiontests/middleware_exceptions/tests.py
--- a/tests/regressiontests/middleware_exceptions/tests.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/middleware_exceptions/tests.py	Sun Nov 28 14:50:46 2010 +0800
@@ -3,9 +3,10 @@
 from django.conf import settings
 from django.core.signals import got_request_exception
 from django.http import HttpResponse
+from django.template.response import TemplateResponse
+from django.template import Template
 from django.test import TestCase
 
-
 class TestException(Exception):
     pass
 
@@ -16,6 +17,7 @@
         self.process_request_called = False
         self.process_view_called = False
         self.process_response_called = False
+        self.process_template_response_called = False
         self.process_exception_called = False
 
     def process_request(self, request):
@@ -24,6 +26,10 @@
     def process_view(self, request, view_func, view_args, view_kwargs):
         self.process_view_called = True
 
+    def process_template_response(self, request, response):
+        self.process_template_response_called = True
+        return response
+
     def process_response(self, request, response):
         self.process_response_called = True
         return response
@@ -48,6 +54,11 @@
         super(ResponseMiddleware, self).process_response(request, response)
         return HttpResponse('Response Middleware')
 
+class TemplateResponseMiddleware(TestMiddleware):
+    def process_template_response(self, request, response):
+        super(TemplateResponseMiddleware, self).process_template_response(request, response)
+        return TemplateResponse(request, Template('Template Response Middleware'))
+
 class ExceptionMiddleware(TestMiddleware):
     def process_exception(self, request, exception):
         super(ExceptionMiddleware, self).process_exception(request, exception)
@@ -66,6 +77,11 @@
         super(BadViewMiddleware, self).process_view(request, view_func, view_args, view_kwargs)
         raise TestException('Test View Exception')
 
+class BadTemplateResponseMiddleware(TestMiddleware):
+    def process_template_response(self, request, response):
+        super(BadTemplateResponseMiddleware, self).process_template_response(request, response)
+        raise TestException('Test Template Response Exception')
+
 class BadResponseMiddleware(TestMiddleware):
     def process_response(self, request, response):
         super(BadResponseMiddleware, self).process_response(request, response)
@@ -93,6 +109,7 @@
     def _add_middleware(self, middleware):
         self.client.handler._request_middleware.insert(0, middleware.process_request)
         self.client.handler._view_middleware.insert(0, middleware.process_view)
+        self.client.handler._template_response_middleware.append(middleware.process_template_response)
         self.client.handler._response_middleware.append(middleware.process_response)
         self.client.handler._exception_middleware.append(middleware.process_exception)
 
@@ -113,9 +130,10 @@
             exception, value, tb = self.exceptions[i]
             self.assertEquals(value.args, (error, ))
 
-    def assert_middleware_usage(self, middleware, request, view, response, exception):
+    def assert_middleware_usage(self, middleware, request, view, template_response, response, exception):
         self.assertEqual(middleware.process_request_called, request)
         self.assertEqual(middleware.process_view_called, view)
+        self.assertEqual(middleware.process_template_response_called, template_response)
         self.assertEqual(middleware.process_response_called, response)
         self.assertEqual(middleware.process_exception_called, exception)
 
@@ -132,9 +150,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(middleware,      True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(middleware,      True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_middleware(self):
         pre_middleware = TestMiddleware()
@@ -146,9 +164,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(middleware,      True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_middleware(self):
         pre_middleware = TestMiddleware()
@@ -160,9 +178,23 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True,  False)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
+
+    def test_process_template_response_middleware(self):
+        pre_middleware = TestMiddleware()
+        middleware = TemplateResponseMiddleware()
+        post_middleware = TestMiddleware()
+        self._add_middleware(post_middleware)
+        self._add_middleware(middleware)
+        self._add_middleware(pre_middleware)
+        self.assert_exceptions_handled('/middleware_exceptions/template_response/', [])
+
+        # Check that the right middleware methods have been invoked
+        self.assert_middleware_usage(pre_middleware,  True, True, True, True, False)
+        self.assert_middleware_usage(middleware,      True, True, True, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, True, True, False)
 
     def test_process_exception_middleware(self):
         pre_middleware = TestMiddleware()
@@ -174,9 +206,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
 
     def test_process_request_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -188,9 +220,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(middleware,      True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(middleware,      True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -202,9 +234,23 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(middleware,      True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
+
+    def test_process_template_response_middleware_not_found(self):
+        pre_middleware = TestMiddleware()
+        middleware = TemplateResponseMiddleware()
+        post_middleware = TestMiddleware()
+        self._add_middleware(post_middleware)
+        self._add_middleware(middleware)
+        self._add_middleware(pre_middleware)
+        self.assert_exceptions_handled('/middleware_exceptions/not_found/', [])
+
+        # Check that the right middleware methods have been invoked
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_response_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -216,9 +262,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_exception_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -230,9 +276,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_request_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -244,9 +290,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(middleware,      True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -258,9 +304,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(middleware,      True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -272,9 +318,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', ['Error in view'], Exception())
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_exception_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -286,9 +332,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_request_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -300,9 +346,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/null_view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(middleware,      True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(middleware,      True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -314,9 +360,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/null_view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(middleware,      True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -331,9 +377,9 @@
             ValueError())
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True,  False)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
 
     def test_process_exception_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -348,9 +394,9 @@
             ValueError())
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
 
     def test_process_request_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -362,9 +408,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(middleware,      True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(middleware,      True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -376,9 +422,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,      True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(middleware,      True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -390,9 +436,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(middleware,      True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_exception_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -404,9 +450,18 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(middleware,      True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
+
+    def test_process_template_response_error(self):
+        middleware = TestMiddleware()
+        self._add_middleware(middleware)
+        self.assert_exceptions_handled('/middleware_exceptions/template_response_error/', [])
+
+        # Check that the right middleware methods have been invoked
+        self.assert_middleware_usage(middleware, True, True, True, True, False)
+
 
 class BadMiddlewareTests(BaseMiddlewareExceptionTest):
 
@@ -420,9 +475,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', ['Test Request Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(bad_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_bad_middleware(self):
         pre_middleware = TestMiddleware()
@@ -434,9 +489,23 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', ['Test View Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
+
+    def test_process_template_response_bad_middleware(self):
+        pre_middleware = TestMiddleware()
+        bad_middleware = BadTemplateResponseMiddleware()
+        post_middleware = TestMiddleware()
+        self._add_middleware(post_middleware)
+        self._add_middleware(bad_middleware)
+        self._add_middleware(pre_middleware)
+        self.assert_exceptions_handled('/middleware_exceptions/template_response/', ['Test Template Response Exception'])
+
+        # Check that the right middleware methods have been invoked
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, True,  False, False)
+        self.assert_middleware_usage(post_middleware, True, True, True,  False, False)
 
     def test_process_response_bad_middleware(self):
         pre_middleware = TestMiddleware()
@@ -448,9 +517,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', ['Test Response Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  False, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True,  False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True,  False)
 
     def test_process_exception_bad_middleware(self):
         pre_middleware = TestMiddleware()
@@ -462,9 +531,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/view/', [])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
 
     def test_process_request_bad_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -476,9 +545,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', ['Test Request Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(bad_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_bad_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -490,9 +559,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', ['Test View Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_bad_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -504,9 +573,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', ['Test Response Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  False, True)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, True)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True,  True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True,  True)
 
     def test_process_exception_bad_middleware_not_found(self):
         pre_middleware = TestMiddleware()
@@ -518,9 +587,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/not_found/', ['Test Exception Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_request_bad_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -532,9 +601,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', ['Test Request Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(bad_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_bad_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -546,9 +615,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', ['Test View Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_bad_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -560,9 +629,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', ['Error in view', 'Test Response Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  False, True)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, True)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True,  True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True,  True)
 
     def test_process_exception_bad_middleware_exception(self):
         pre_middleware = TestMiddleware()
@@ -574,9 +643,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/error/', ['Test Exception Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
     def test_process_request_bad_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -588,9 +657,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/null_view/', ['Test Request Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(bad_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_bad_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -602,9 +671,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/null_view/', ['Test View Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_bad_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -619,9 +688,9 @@
             ])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  False, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True,  False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True,  False)
 
     def test_process_exception_bad_middleware_null_view(self):
         pre_middleware = TestMiddleware()
@@ -636,9 +705,9 @@
             ValueError())
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  True,  True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, False)
 
     def test_process_request_bad_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -650,9 +719,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', ['Test Request Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(bad_middleware,  True,  False, True,  False)
-        self.assert_middleware_usage(post_middleware, False, False, True,  False)
+        self.assert_middleware_usage(pre_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True,  False, False, True, False)
+        self.assert_middleware_usage(post_middleware, False, False, False, True, False)
 
     def test_process_view_bad_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -664,9 +733,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', ['Test View Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(post_middleware, True,  False, True, False)
+        self.assert_middleware_usage(pre_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True,  False, True, False)
+        self.assert_middleware_usage(post_middleware, True, False, False, True, False)
 
     def test_process_response_bad_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -678,9 +747,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', ['Test Response Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  False, True)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, False, True)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True,  True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True,  True)
 
     def test_process_exception_bad_middleware_permission_denied(self):
         pre_middleware = TestMiddleware()
@@ -692,9 +761,9 @@
         self.assert_exceptions_handled('/middleware_exceptions/permission_denied/', ['Test Exception Exception'])
 
         # Check that the right middleware methods have been invoked
-        self.assert_middleware_usage(pre_middleware,  True,  True,  True, False)
-        self.assert_middleware_usage(bad_middleware,  True,  True,  True,  True)
-        self.assert_middleware_usage(post_middleware, True,  True,  True,  True)
+        self.assert_middleware_usage(pre_middleware,  True, True, False, True, False)
+        self.assert_middleware_usage(bad_middleware,  True, True, False, True, True)
+        self.assert_middleware_usage(post_middleware, True, True, False, True, True)
 
 
 _missing = object()
diff -r 78ad3faa689b tests/regressiontests/middleware_exceptions/urls.py
--- a/tests/regressiontests/middleware_exceptions/urls.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/middleware_exceptions/urls.py	Sun Nov 28 14:50:46 2010 +0800
@@ -9,4 +9,7 @@
     (r'^error/$', views.server_error),
     (r'^null_view/$', views.null_view),
     (r'^permission_denied/$', views.permission_denied),
+
+    (r'^template_response/$', views.template_response),
+    (r'^template_response_error/$', views.template_response_error),
 )
diff -r 78ad3faa689b tests/regressiontests/middleware_exceptions/views.py
--- a/tests/regressiontests/middleware_exceptions/views.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/middleware_exceptions/views.py	Sun Nov 28 14:50:46 2010 +0800
@@ -1,9 +1,17 @@
 from django import http
 from django.core.exceptions import PermissionDenied
+from django.shortcuts import render
+from django.template import Template
 
 def normal_view(request):
     return http.HttpResponse('OK')
 
+def template_response(request):
+    return render(request, Template('OK'))
+
+def template_response_error(request):
+    return render(request, Template('{%'))
+
 def not_found(request):
     raise http.Http404()
 
diff -r 78ad3faa689b tests/regressiontests/templates/response.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/templates/response.py	Sun Nov 28 14:50:46 2010 +0800
@@ -0,0 +1,174 @@
+import os
+from django.utils import unittest
+from django.test import RequestFactory
+from django.conf import settings
+import django.template.context
+from django.template import Template, Context, RequestContext
+from django.template.response import (TemplateResponse, SimpleTemplateResponse,
+                                      ContentNotBakedError)
+
+def test_processor(request):
+    return {'processors': 'yes'}
+test_processor_name = 'regressiontests.templates.response.test_processor'
+
+class BaseTemplateResponseTest(unittest.TestCase):
+    # tests rely on fact that global context
+    # processors should only work when RequestContext is used.
+
+    def setUp(self):
+        self.factory = RequestFactory()
+        self._old_processors = settings.TEMPLATE_CONTEXT_PROCESSORS
+        self._old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS
+        settings.TEMPLATE_CONTEXT_PROCESSORS = [test_processor_name]
+        settings.TEMPLATE_DIRS = (
+            os.path.join(
+                os.path.dirname(__file__),
+                'templates'
+            ),
+        )
+        # Force re-evaluation of the contex processor list
+        django.template.context._standard_context_processors = None
+
+    def tearDown(self):
+        settings.TEMPLATE_DIRS = self._old_TEMPLATE_DIRS
+        settings.TEMPLATE_CONTEXT_PROCESSORS = self._old_processors
+        # Force re-evaluation of the contex processor list
+        django.template.context._standard_context_processors = None
+
+
+class SimpleTemplateResponseTest(BaseTemplateResponseTest):
+
+    def _response(self, template='foo', *args, **kwargs):
+        return SimpleTemplateResponse(Template(template), *args, **kwargs)
+
+    def test_template_resolving(self):
+        response = SimpleTemplateResponse('first/test.html')
+        response.bake()
+        self.assertEqual('First template\n', response.content)
+
+        templates = ['foo.html', 'second/test.html', 'first/test.html']
+        response = SimpleTemplateResponse(templates)
+        response.bake()
+        self.assertEqual('Second template\n', response.content)
+
+        response = self._response()
+        response.bake()
+        self.assertEqual(response.content, 'foo')
+
+    def test_explicit_baking(self):
+        # explicit baking
+        response = self._response()
+        self.assertFalse(response.baked)
+        response.bake()
+        self.assertTrue(response.baked)
+
+    def test_bake(self):
+        # response is not re-baked without the bake call
+        response = self._response().bake()
+        self.assertEqual(response.content, 'foo')
+
+        # rebaking doesn't change the baked content
+        response.template_name = Template('bar{{ baz }}')
+        response.bake()
+        self.assertEqual(response.content, 'foo')
+
+        # but baked content can be overridden by manually
+        # setting content
+        response.content = 'bar'
+        self.assertEqual(response.content, 'bar')
+
+    def test_iteration_unbaked(self):
+        # unbaked response raises an exception on iteration
+        response = self._response()
+        self.assertFalse(response.baked)
+
+        def iteration():
+            for x in response:
+                pass
+        self.assertRaises(ContentNotBakedError, iteration)
+        self.assertFalse(response.baked)
+
+    def test_iteration_baked(self):
+        # iteration works for baked responses
+        response = self._response().bake()
+        res = [x for x in response]
+        self.assertEqual(res, ['foo'])
+
+    def test_content_access_unbaked(self):
+        # unbaked response raises an exception when content is accessed
+        response = self._response()
+        self.assertFalse(response.baked)
+        self.assertRaises(ContentNotBakedError, lambda: response.content)
+        self.assertFalse(response.baked)
+
+    def test_content_access_baked(self):
+        # baked response content can be accessed
+        response = self._response().bake()
+        self.assertEqual(response.content, 'foo')
+
+    def test_set_content(self):
+        # content can be overriden
+        response = self._response()
+        self.assertFalse(response.baked)
+        response.content = 'spam'
+        self.assertTrue(response.baked)
+        self.assertEqual(response.content, 'spam')
+        response.content = 'baz'
+        self.assertEqual(response.content, 'baz')
+
+    def test_dict_context(self):
+        response = self._response('{{ foo }}{{ processors }}',
+                                  {'foo': 'bar'})
+        self.assertEqual(response.context_data, {'foo': 'bar'})
+        response.bake()
+        self.assertEqual(response.content, 'bar')
+
+    def test_context_instance(self):
+        response = self._response('{{ foo }}{{ processors }}',
+                                  Context({'foo': 'bar'}))
+        self.assertEqual(response.context_data.__class__, Context)
+        response.bake()
+        self.assertEqual(response.content, 'bar')
+
+    def test_kwargs(self):
+        response = self._response(content_type = 'application/json', status=504)
+        self.assertEqual(response['content-type'], 'application/json')
+        self.assertEqual(response.status_code, 504)
+
+    def test_args(self):
+        response = SimpleTemplateResponse('', {}, 'application/json', 504)
+        self.assertEqual(response['content-type'], 'application/json')
+        self.assertEqual(response.status_code, 504)
+
+
+class TemplateResponseTest(BaseTemplateResponseTest):
+
+    def _response(self, template='foo', *args, **kwargs):
+        return TemplateResponse(self.factory.get('/'), Template(template),
+                                *args, **kwargs)
+
+    def test_render(self):
+        response = self._response('{{ foo }}{{ processors }}').bake()
+        self.assertEqual(response.content, 'yes')
+
+    def test_render_with_requestcontext(self):
+        response = self._response('{{ foo }}{{ processors }}',
+                                  {'foo': 'bar'}).bake()
+        self.assertEqual(response.content, 'baryes')
+
+    def test_render_with_context(self):
+        response = self._response('{{ foo }}{{ processors }}',
+                                  Context({'foo': 'bar'})).bake()
+        self.assertEqual(response.content, 'bar')
+
+    def test_kwargs(self):
+        response = self._response(content_type = 'application/json',
+                                  status=504)
+        self.assertEqual(response['content-type'], 'application/json')
+        self.assertEqual(response.status_code, 504)
+
+    def test_args(self):
+        response = TemplateResponse(self.factory.get('/'), '', {},
+                                    'application/json', 504)
+        self.assertEqual(response['content-type'], 'application/json')
+        self.assertEqual(response.status_code, 504)
diff -r 78ad3faa689b tests/regressiontests/templates/tests.py
--- a/tests/regressiontests/templates/tests.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/templates/tests.py	Sun Nov 28 14:50:46 2010 +0800
@@ -28,6 +28,7 @@
 from unicode import UnicodeTests
 from nodelist import NodelistTest
 from smartif import *
+from response import *
 
 try:
     from loaders import *
diff -r 78ad3faa689b tests/regressiontests/views/templates/debug/render_test.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/views/templates/debug/render_test.html	Sun Nov 28 14:50:46 2010 +0800
@@ -0,0 +1,1 @@
+{{ foo }}.{{ bar }}.{{ baz }}.{{ processors }}
diff -r 78ad3faa689b tests/regressiontests/views/tests/__init__.py
--- a/tests/regressiontests/views/tests/__init__.py	Sat Nov 27 05:47:30 2010 +0000
+++ b/tests/regressiontests/views/tests/__init__.py	Sun Nov 28 14:50:46 2010 +0800
@@ -7,3 +7,4 @@
 from i18n import *
 from specials import *
 from static import *
+from shortcuts import *
diff -r 78ad3faa689b tests/regressiontests/views/tests/shortcuts.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/regressiontests/views/tests/shortcuts.py	Sun Nov 28 14:50:46 2010 +0800
@@ -0,0 +1,20 @@
+from django.test import RequestFactory
+from django.template import Template
+from django.shortcuts import render
+
+from regressiontests.templates.response import BaseTemplateResponseTest
+
+def test_view(request):
+    return render(request, 'debug/render_test.html',
+                  {'foo': 'foo', 'baz': 'baz'})
+
+
+class RenderTest(BaseTemplateResponseTest):
+
+    def setUp(self):
+        super(RenderTest, self).setUp()
+        self.request = self.factory.get('/')
+
+    def test_simple_view(self):
+        response = test_view(self.request)
+        self.assertEqual(response.content, 'foo..baz.yes\n')
