Fixed #12815 -- Added TemplateResponse, a lazy-evaluated Response class. Thanks to Simon Willison for the original idea, and to Mikhail Korobov and Ivan Sagalaev for their assistance, including the draft patch from Mikhail.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14850 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
22fc30be5a
commit
e0dcd7666a
1
AUTHORS
1
AUTHORS
|
@ -273,6 +273,7 @@ answer newbie questions, and generally made Django that much better:
|
|||
Igor Kolar <ike@email.si>
|
||||
Tomáš Kopeček <permonik@m6.cz>
|
||||
Gasper Koren
|
||||
Mikhail Korobov <kmike84@googlemail.com>
|
||||
Martin Kosír <martin@martinkosir.net>
|
||||
Arthur Koziel <http://arthurkoziel.com>
|
||||
Meir Kriheli <http://mksoft.co.il/>
|
||||
|
|
|
@ -103,7 +103,7 @@ class BaseTest(TestCase):
|
|||
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 @@ class BaseTest(TestCase):
|
|||
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
|
||||
|
|
|
@ -2,9 +2,20 @@ from django.conf.urls.defaults import *
|
|||
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 @@ def add(request, message_type):
|
|||
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),
|
||||
)
|
||||
|
|
|
@ -21,6 +21,7 @@ class BaseHandler(object):
|
|||
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,16 +31,16 @@ class BaseHandler(object):
|
|||
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('.')
|
||||
mw_module, mw_classname = middleware_path.rsplit('.', 1)
|
||||
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:
|
||||
|
@ -48,7 +49,6 @@ class BaseHandler(object):
|
|||
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()
|
||||
except exceptions.MiddlewareNotUsed:
|
||||
|
@ -58,6 +58,8 @@ class BaseHandler(object):
|
|||
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 +166,13 @@ class BaseHandler(object):
|
|||
urlresolvers.set_urlconf(None)
|
||||
|
||||
try:
|
||||
# If the response supports deferred rendering, apply template
|
||||
# response middleware and the render the response
|
||||
if hasattr(response, 'render') and callable(response.render):
|
||||
for middleware_method in self._template_response_middleware:
|
||||
response = middleware_method(request, response)
|
||||
response.render()
|
||||
|
||||
# Apply response middleware, regardless of the response
|
||||
for middleware_method in self._response_middleware:
|
||||
response = middleware_method(request, response)
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
from django.http import HttpResponse
|
||||
from django.template import loader, Context, RequestContext
|
||||
|
||||
class ContentNotRenderedError(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
|
||||
|
||||
# _is_rendered tracks whether the template and context has been baked into
|
||||
# a final response.
|
||||
self._is_rendered = 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)
|
||||
|
||||
@property
|
||||
def rendered_content(self):
|
||||
"""Returns the freshly rendered content for the template and context
|
||||
described by the TemplateResponse.
|
||||
|
||||
This *does not* set the final content of the response. To set the
|
||||
response content, you must either call render(), or set the
|
||||
content explicitly using the value of this property.
|
||||
"""
|
||||
template = self.resolve_template(self.template_name)
|
||||
context = self.resolve_context(self.context_data)
|
||||
content = template.render(context)
|
||||
return content
|
||||
|
||||
def render(self):
|
||||
"""Render (thereby finalizing) the content of the response.
|
||||
|
||||
If the content has already been rendered, this is a no-op.
|
||||
|
||||
Returns the baked response instance.
|
||||
"""
|
||||
if not self._is_rendered:
|
||||
self._set_content(self.rendered_content)
|
||||
return self
|
||||
|
||||
is_rendered = property(lambda self: self._is_rendered)
|
||||
|
||||
def __iter__(self):
|
||||
if not self._is_rendered:
|
||||
raise ContentNotRenderedError('The response content must be rendered before it can be iterated over.')
|
||||
return super(SimpleTemplateResponse, self).__iter__()
|
||||
|
||||
def _get_content(self):
|
||||
if not self._is_rendered:
|
||||
raise ContentNotRenderedError('The response content must be rendered before it can be accessed.')
|
||||
return super(SimpleTemplateResponse, self)._get_content()
|
||||
|
||||
def _set_content(self, value):
|
||||
"Overrides rendered content, unless you later call render()"
|
||||
super(SimpleTemplateResponse, self)._set_content(value)
|
||||
self._is_rendered = 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)
|
|
@ -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 @@ class TemplateResponseMixin(object):
|
|||
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):
|
||||
"""
|
||||
|
|
|
@ -93,7 +93,9 @@ The view layer
|
|||
: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>` |
|
||||
|
|
|
@ -76,39 +76,25 @@ TemplateResponseMixin
|
|||
|
||||
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 @@ TemplateResponseMixin
|
|||
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
|
||||
--------------------
|
||||
|
|
|
@ -16,6 +16,7 @@ API Reference
|
|||
middleware
|
||||
models/index
|
||||
request-response
|
||||
template-response
|
||||
settings
|
||||
signals
|
||||
templates/index
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
===========================================
|
||||
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, later in the response process.
|
||||
|
||||
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}``
|
||||
|
||||
.. attr:: SimpleTemplateResponse.rendered_content:
|
||||
|
||||
The current rendered value of the response content, using the current
|
||||
template and context data.
|
||||
|
||||
.. attr:: SimpleTemplateResponse.is_rendered:
|
||||
|
||||
A boolean indicating whether the response content has been rendered.
|
||||
|
||||
|
||||
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():
|
||||
|
||||
Sets :attr:`response.content` to the result obtained by
|
||||
:attr:`SimpleTemplateResponse.rendered_content`.
|
||||
|
||||
:meth:`~SimpleTemplateResponse.render()` will only have an effect
|
||||
the first time it is called. On subsequent calls, it will return
|
||||
the result obtained from the first call.
|
||||
|
||||
|
||||
.. 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.
|
||||
|
||||
|
||||
The rendering process
|
||||
=====================
|
||||
|
||||
Before a :class:`TemplateResponse()` instance can be returned to the
|
||||
client, it must be rendered. The rendering process takes the
|
||||
intermediate representation of template and context, and turns it into
|
||||
the final byte stream that can be served to the client.
|
||||
|
||||
There are three circumstances under which a TemplateResponse will be
|
||||
rendered:
|
||||
|
||||
* When the TemplateResponse instance is explicitly rendered, using
|
||||
the :meth:`SimpleTemplateResponse.render()` 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 rendered once. The first call to
|
||||
:meth:`SimpleTemplateResponse.render()` sets the content of the
|
||||
response; subsequent rendering 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 the content to be
|
||||
re-rendered, you can re-evaluate the rendered content, and assign
|
||||
the content of the response manually::
|
||||
|
||||
# Set up a baked TemplateResponse
|
||||
>>> t = TemplateResponse(request, 'original.html', {})
|
||||
>>> t.render()
|
||||
>>> print t.content
|
||||
Original content
|
||||
|
||||
# Rebaking doesn't change content
|
||||
>>> t.template_name = 'new.html'
|
||||
>>> t.render()
|
||||
>>> print t.content
|
||||
Original content
|
||||
|
||||
# Assigning content does change, no render() call required
|
||||
>>> t.content = t.rendered_content
|
||||
>>> print t.content
|
||||
New 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 :method:`~django.shortcuts.render_to_response()`.
|
||||
|
||||
For example, the following simple view returns a
|
||||
:class:`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()})
|
|
@ -133,6 +133,27 @@ can also add special translator comments in the source.
|
|||
For more information, see :ref:`contextual-markers` and
|
||||
:ref:`translator-comments`.
|
||||
|
||||
TemplateResponse
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
However, you can't (easily) modify the content of a basic
|
||||
:class:`~django.http.HttpResponse` after it has been constructed. To
|
||||
overcome this limitation, Django 1.3 adds a new
|
||||
:class:`~django.template.TemplateResponse` class. Unlike basic
|
||||
:class:`~django.http.HttpResponse` objects,
|
||||
:class:`~django.template.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, later in the response process.
|
||||
|
||||
For more details, see the :ref:`documentation </ref/template-response>`
|
||||
on the :class:`~django.template.TemplateResponse` class.
|
||||
|
||||
Everything else
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -97,6 +97,39 @@ calling ANY other request, view or exception middleware, or the appropriate
|
|||
view; it'll return that :class:`~django.http.HttpResponse`. Response
|
||||
middleware is always called on every response.
|
||||
|
||||
.. _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()`` will only be called if the response
|
||||
instance has a ``render()`` method, indicating that it is a
|
||||
:class:`~django.template.response.TemplateResponse`.
|
||||
|
||||
You don't need to explicitly render responses -- responses will be
|
||||
automatically rendered once all template response middleware has been
|
||||
called.
|
||||
|
||||
Middleware are run in reverse order during the response phase, which
|
||||
includes process_template_response.
|
||||
|
||||
.. _response-middleware:
|
||||
|
||||
``process_response``
|
||||
|
@ -120,6 +153,7 @@ an earlier middleware method returned an :class:`~django.http.HttpResponse`
|
|||
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.
|
||||
|
||||
|
||||
.. _exception-middleware:
|
||||
|
||||
``process_exception``
|
||||
|
@ -137,7 +171,7 @@ Django calls ``process_exception()`` when a view raises an exception.
|
|||
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__``
|
||||
|
|
|
@ -156,6 +156,7 @@ class TemplateViewTest(TestCase):
|
|||
rf = RequestFactory()
|
||||
|
||||
def _assert_about(self, response):
|
||||
response.render()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, '<h1>About</h1>')
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@ import sys
|
|||
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 @@ class TestMiddleware(object):
|
|||
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 @@ class TestMiddleware(object):
|
|||
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 @@ class ResponseMiddleware(TestMiddleware):
|
|||
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 @@ class BadViewMiddleware(TestMiddleware):
|
|||
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 @@ class BaseMiddlewareExceptionTest(TestCase):
|
|||
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 @@ class BaseMiddlewareExceptionTest(TestCase):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
])
|
||||
|
||||
# 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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
|||
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()
|
||||
|
|
|
@ -9,4 +9,7 @@ urlpatterns = patterns('',
|
|||
(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),
|
||||
)
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
from django import http
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.template import Template
|
||||
from django.template.response import TemplateResponse
|
||||
|
||||
|
||||
def normal_view(request):
|
||||
return http.HttpResponse('OK')
|
||||
|
||||
def template_response(request):
|
||||
return TemplateResponse(request, Template('OK'))
|
||||
|
||||
def template_response_error(request):
|
||||
return TemplateResponse(request, Template('{%'))
|
||||
|
||||
def not_found(request):
|
||||
raise http.Http404()
|
||||
|
||||
|
|
|
@ -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,
|
||||
ContentNotRenderedError)
|
||||
|
||||
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.render()
|
||||
self.assertEqual('First template\n', response.content)
|
||||
|
||||
templates = ['foo.html', 'second/test.html', 'first/test.html']
|
||||
response = SimpleTemplateResponse(templates)
|
||||
response.render()
|
||||
self.assertEqual('Second template\n', response.content)
|
||||
|
||||
response = self._response()
|
||||
response.render()
|
||||
self.assertEqual(response.content, 'foo')
|
||||
|
||||
def test_explicit_baking(self):
|
||||
# explicit baking
|
||||
response = self._response()
|
||||
self.assertFalse(response.is_rendered)
|
||||
response.render()
|
||||
self.assertTrue(response.is_rendered)
|
||||
|
||||
def test_render(self):
|
||||
# response is not re-rendered without the render call
|
||||
response = self._response().render()
|
||||
self.assertEqual(response.content, 'foo')
|
||||
|
||||
# rebaking doesn't change the rendered content
|
||||
response.template_name = Template('bar{{ baz }}')
|
||||
response.render()
|
||||
self.assertEqual(response.content, 'foo')
|
||||
|
||||
# but rendered content can be overridden by manually
|
||||
# setting content
|
||||
response.content = 'bar'
|
||||
self.assertEqual(response.content, 'bar')
|
||||
|
||||
def test_iteration_unrendered(self):
|
||||
# unrendered response raises an exception on iteration
|
||||
response = self._response()
|
||||
self.assertFalse(response.is_rendered)
|
||||
|
||||
def iteration():
|
||||
for x in response:
|
||||
pass
|
||||
self.assertRaises(ContentNotRenderedError, iteration)
|
||||
self.assertFalse(response.is_rendered)
|
||||
|
||||
def test_iteration_rendered(self):
|
||||
# iteration works for rendered responses
|
||||
response = self._response().render()
|
||||
res = [x for x in response]
|
||||
self.assertEqual(res, ['foo'])
|
||||
|
||||
def test_content_access_unrendered(self):
|
||||
# unrendered response raises an exception when content is accessed
|
||||
response = self._response()
|
||||
self.assertFalse(response.is_rendered)
|
||||
self.assertRaises(ContentNotRenderedError, lambda: response.content)
|
||||
self.assertFalse(response.is_rendered)
|
||||
|
||||
def test_content_access_rendered(self):
|
||||
# rendered response content can be accessed
|
||||
response = self._response().render()
|
||||
self.assertEqual(response.content, 'foo')
|
||||
|
||||
def test_set_content(self):
|
||||
# content can be overriden
|
||||
response = self._response()
|
||||
self.assertFalse(response.is_rendered)
|
||||
response.content = 'spam'
|
||||
self.assertTrue(response.is_rendered)
|
||||
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.render()
|
||||
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.render()
|
||||
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 }}').render()
|
||||
self.assertEqual(response.content, 'yes')
|
||||
|
||||
def test_render_with_requestcontext(self):
|
||||
response = self._response('{{ foo }}{{ processors }}',
|
||||
{'foo': 'bar'}).render()
|
||||
self.assertEqual(response.content, 'baryes')
|
||||
|
||||
def test_render_with_context(self):
|
||||
response = self._response('{{ foo }}{{ processors }}',
|
||||
Context({'foo': 'bar'})).render()
|
||||
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)
|
|
@ -28,6 +28,7 @@ from parser import ParserTests
|
|||
from unicode import UnicodeTests
|
||||
from nodelist import NodelistTest
|
||||
from smartif import *
|
||||
from response import *
|
||||
|
||||
try:
|
||||
from loaders import *
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{{ foo }}.{{ bar }}.{{ baz }}.{{ processors }}
|
Loading…
Reference in New Issue