Accounted for multiple template engines in template responses.

This commit is contained in:
Aymeric Augustin 2015-01-09 22:59:00 +01:00
parent a3e783fe11
commit 79deb6a071
11 changed files with 215 additions and 111 deletions

View File

@ -3,7 +3,7 @@ from django.contrib import messages
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django import forms from django import forms
from django.http import HttpResponseRedirect, HttpResponse from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext, Template from django.template import engines
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.views.decorators.cache import never_cache from django.views.decorators.cache import never_cache
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
@ -48,13 +48,14 @@ def add_template_response(request, message_type):
@never_cache @never_cache
def show(request): def show(request):
t = Template(TEMPLATE) template = engines['django'].from_string(TEMPLATE)
return HttpResponse(t.render(RequestContext(request))) return HttpResponse(template.render(request=request))
@never_cache @never_cache
def show_template_response(request): def show_template_response(request):
return TemplateResponse(request, Template(TEMPLATE)) template = engines['django'].from_string(TEMPLATE)
return TemplateResponse(request, template)
class ContactForm(forms.Form): class ContactForm(forms.Form):

View File

@ -1,7 +1,8 @@
import warnings import warnings
from django.http import HttpResponse from django.http import HttpResponse
from django.template import loader, Context, RequestContext from django.template import loader, Context, RequestContext, Template
from django.template.backends.django import Template as BackendTemplate
from django.template.context import _current_app_undefined from django.template.context import _current_app_undefined
from django.utils import six from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning from django.utils.deprecation import RemovedInDjango20Warning
@ -16,14 +17,30 @@ class SimpleTemplateResponse(HttpResponse):
def __init__(self, template, context=None, content_type=None, status=None, def __init__(self, template, context=None, content_type=None, status=None,
charset=None): charset=None):
if isinstance(template, Template):
warnings.warn(
"{}'s template argument cannot be a django.template.Template "
"anymore. It may be a backend-specific template like those "
"created by get_template().".format(self.__class__.__name__),
RemovedInDjango20Warning, stacklevel=2)
template = BackendTemplate(template)
# It would seem obvious to call these next two members 'template' and # It would seem obvious to call these next two members 'template' and
# 'context', but those names are reserved as part of the test Client # 'context', but those names are reserved as part of the test Client
# API. To avoid the name collision, we use tricky-to-debug problems # API. To avoid the name collision, we use different names.
self.template_name = template self.template_name = template
self.context_data = context self.context_data = context
self._post_render_callbacks = [] self._post_render_callbacks = []
# _request stores the current request object in subclasses that know
# about requests, like TemplateResponse. It's defined in the base class
# to minimize code duplication.
# It's called self._request because self.request gets overwritten by
# django.test.client.Client. Unlike template_name and context_data,
# _request should not be considered part of the public API.
self._request = None
# content argument doesn't make sense here because it will be replaced # content argument doesn't make sense here because it will be replaced
# with rendered template so we always pass empty string in order to # with rendered template so we always pass empty string in order to
# prevent errors and provide shorter signature. # prevent errors and provide shorter signature.
@ -62,14 +79,45 @@ class SimpleTemplateResponse(HttpResponse):
else: else:
return template return template
def _resolve_template(self, template):
# This wrapper deprecates returning a django.template.Template in
# subclasses that override resolve_template. It can be removed in
# Django 2.0.
new_template = self.resolve_template(template)
if isinstance(new_template, Template):
warnings.warn(
"{}.resolve_template() must return a backend-specific "
"template like those created by get_template(), not a "
"{}.".format(
self.__class__.__name__, new_template.__class__.__name__),
RemovedInDjango20Warning, stacklevel=2)
new_template = BackendTemplate(new_template)
return new_template
def resolve_context(self, context): def resolve_context(self, context):
"""Converts context data into a full Context object return context
(assuming it isn't already a Context object).
""" def _resolve_context(self, context):
if isinstance(context, Context): # This wrapper deprecates returning a Context or a RequestContext in
return context # subclasses that override resolve_context. It can be removed in
else: # Django 2.0. If returning a Context or a RequestContext works by
return Context(context) # accident, it won't be an issue per se, but it won't be officially
# supported either.
new_context = self.resolve_context(context)
if isinstance(new_context, RequestContext) and self._request is None:
self._request = new_context.request
if isinstance(new_context, Context):
warnings.warn(
"{}.resolve_context() must return a dict, not a {}.".format(
self.__class__.__name__, new_context.__class__.__name__),
RemovedInDjango20Warning, stacklevel=2)
# It would be tempting to do new_context = new_context.flatten()
# here but that would cause template context processors to run for
# TemplateResponse(request, template, Context({})), which would be
# backwards-incompatible. As a consequence another deprecation
# warning will be raised when rendering the template. There isn't
# much we can do about that.
return new_context
@property @property
def rendered_content(self): def rendered_content(self):
@ -80,14 +128,9 @@ class SimpleTemplateResponse(HttpResponse):
response content, you must either call render(), or set the response content, you must either call render(), or set the
content explicitly using the value of this property. content explicitly using the value of this property.
""" """
template = self.resolve_template(self.template_name) template = self._resolve_template(self.template_name)
context = self.resolve_context(self.context_data) context = self._resolve_context(self.context_data)
# TODO - remove this hack - makes the tests pass until the next commit content = template.render(context, self._request)
try:
template = template.template
except AttributeError:
pass
content = template.render(context)
return content return content
def add_post_render_callback(self, callback): def add_post_render_callback(self, callback):
@ -147,10 +190,6 @@ class TemplateResponse(SimpleTemplateResponse):
def __init__(self, request, template, context=None, content_type=None, def __init__(self, request, template, context=None, content_type=None,
status=None, current_app=_current_app_undefined, charset=None): status=None, current_app=_current_app_undefined, charset=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
# As a convenience we'll allow callers to provide current_app without # As a convenience we'll allow callers to provide current_app without
# having to avoid needing to create the RequestContext directly # having to avoid needing to create the RequestContext directly
if current_app is not _current_app_undefined: if current_app is not _current_app_undefined:
@ -161,14 +200,4 @@ class TemplateResponse(SimpleTemplateResponse):
request.current_app = current_app request.current_app = current_app
super(TemplateResponse, self).__init__( super(TemplateResponse, self).__init__(
template, context, content_type, status, charset) template, context, content_type, status, charset)
self._request = request
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
context_instance = RequestContext(self._request)
if context:
context_instance.push(context)
return context_instance

View File

@ -114,6 +114,11 @@ details on these changes.
:class:`~django.template.Context` in their :class:`~django.template.Context` in their
:meth:`~django.template.backends.base.Template.render()` method anymore. :meth:`~django.template.backends.base.Template.render()` method anymore.
* :doc:`Template response APIs </ref/template-response>` will enforce the use
of :class:`dict` and backend-dependent template objects instead of
:class:`~django.template.Context` and :class:`~django.template.Template`
respectively.
* The ``current_app`` parameter for the following function and classes will be * The ``current_app`` parameter for the following function and classes will be
removed: removed:

View File

@ -31,19 +31,28 @@ Attributes
.. attribute:: SimpleTemplateResponse.template_name .. attribute:: SimpleTemplateResponse.template_name
The name of the template to be rendered. Accepts a The name of the template to be rendered. Accepts a backend-dependent
:class:`~django.template.Template` object, a path to a template or list template object (such as those returned by
of template paths. :func:`~django.template.loader.get_template()`), the name of a template,
or a list of template names.
Example: ``['foo.html', 'path/to/bar.html']`` Example: ``['foo.html', 'path/to/bar.html']``
.. deprecated:: 1.8
``template_name`` used to accept a :class:`~django.template.Template`.
.. attribute:: SimpleTemplateResponse.context_data .. attribute:: SimpleTemplateResponse.context_data
The context data to be used when rendering the template. It can be The context data to be used when rendering the template. It must be a
a dictionary or a context object. :class:`dict`.
Example: ``{'foo': 123}`` Example: ``{'foo': 123}``
.. deprecated:: 1.8
``context_data`` used to accept a :class:`~django.template.Context`.
.. attribute:: SimpleTemplateResponse.rendered_content .. attribute:: SimpleTemplateResponse.rendered_content
The current rendered value of the response content, using the current The current rendered value of the response content, using the current
@ -58,21 +67,26 @@ Methods
.. method:: SimpleTemplateResponse.__init__(template, context=None, content_type=None, status=None, charset=None) .. method:: SimpleTemplateResponse.__init__(template, context=None, content_type=None, status=None, charset=None)
Instantiates a Instantiates a :class:`~django.template.response.SimpleTemplateResponse`
:class:`~django.template.response.SimpleTemplateResponse` object object with the given template, context, content type, HTTP status, and
with the given template, context, content type, and HTTP status. charset.
``template`` ``template``
The full name of a template, or a sequence of template names. A backend-dependent template object (such as those returned by
:class:`~django.template.Template` instances can also be used. :func:`~django.template.loader.get_template()`), the name of a template,
or a list of template names.
.. deprecated:: 1.8
``template`` used to accept a :class:`~django.template.Template`.
``context`` ``context``
A dictionary of values to add to the template context. By default, A :class:`dict` of values to add to the template context. By default,
this is an empty dictionary. :class:`~django.template.Context` objects this is an empty dictionary.
are also accepted as ``context`` values.
``status`` .. deprecated:: 1.8
The HTTP Status code for the response.
``context`` used to accept a :class:`~django.template.Context`.
``content_type`` ``content_type``
The value included in the HTTP ``Content-Type`` header, including the The value included in the HTTP ``Content-Type`` header, including the
@ -80,6 +94,9 @@ Methods
``content_type`` is specified, then its value is used. Otherwise, ``content_type`` is specified, then its value is used. Otherwise,
:setting:`DEFAULT_CONTENT_TYPE` is used. :setting:`DEFAULT_CONTENT_TYPE` is used.
``status``
The HTTP status code for the response.
``charset`` ``charset``
The charset in which the response will be encoded. If not given it will The charset in which the response will be encoded. If not given it will
be extracted from ``content_type``, and if that is unsuccessful, the be extracted from ``content_type``, and if that is unsuccessful, the
@ -91,22 +108,42 @@ Methods
.. method:: SimpleTemplateResponse.resolve_context(context) .. method:: SimpleTemplateResponse.resolve_context(context)
Converts context data into a context instance that can be used for Preprocesses context data that will be used for rendering a template.
rendering a template. Accepts a dictionary of context data or a Accepts a :class:`dict` of context data. By default, returns the same
context object. Returns a :class:`~django.template.Context` :class:`dict`.
instance containing the provided data.
Override this method in order to customize context instantiation. Override this method in order to customize the context.
.. versionchanged:: 1.8
``resolve_context`` returns a :class:`dict`. It used to return a
:class:`~django.template.Context`.
.. deprecated:: 1.8
``resolve_context`` no longer accepts a
:class:`~django.template.Context`.
.. method:: SimpleTemplateResponse.resolve_template(template) .. method:: SimpleTemplateResponse.resolve_template(template)
Resolves the template instance to use for rendering. Accepts a Resolves the template instance to use for rendering. Accepts a
path of a template to use, or a sequence of template paths. backend-dependent template object (such as those returned by
:class:`~django.template.Template` instances may also be provided. :func:`~django.template.loader.get_template()`), the name of a template,
Returns the :class:`~django.template.Template` instance to be or a list of template names.
rendered.
Override this method in order to customize template rendering. Returns the backend-dependent template object instance to be rendered.
Override this method in order to customize template loading.
.. versionchanged:: 1.8
``resolve_template`` returns backend-dependent template object. It
used to return a :class:`~django.template.Template`.
.. deprecated:: 1.8
``resolve_template`` no longer accepts a
:class:`~django.template.Template`.
.. method:: SimpleTemplateResponse.add_post_render_callback() .. method:: SimpleTemplateResponse.add_post_render_callback()
@ -142,34 +179,37 @@ TemplateResponse objects
.. class:: TemplateResponse() .. class:: TemplateResponse()
``TemplateResponse`` is a subclass of ``TemplateResponse`` is a subclass of
:class:`~django.template.response.SimpleTemplateResponse` that uses :class:`~django.template.response.SimpleTemplateResponse` that knows about
a :class:`~django.template.RequestContext` instead of the current :class:`~django.http.HttpRequest`.
a :class:`~django.template.Context`.
Methods Methods
------- -------
.. method:: TemplateResponse.__init__(request, template, context=None, content_type=None, status=None, current_app=None, charset=None) .. method:: TemplateResponse.__init__(request, template, context=None, content_type=None, status=None, current_app=None, charset=None)
Instantiates an ``TemplateResponse`` object with the given Instantiates a :class:`~django.template.response.TemplateResponse` object
template, context, MIME type and HTTP status. with the given request, template, context, content type, HTTP status, and
charset.
``request`` ``request``
An :class:`~django.http.HttpRequest` instance. An :class:`~django.http.HttpRequest` instance.
``template`` ``template``
The full name of a template, or a sequence of template names. A backend-dependent template object (such as those returned by
:class:`~django.template.Template` instances can also be used. :func:`~django.template.loader.get_template()`), the name of a template,
or a list of template names.
.. deprecated:: 1.8
``template`` used to accept a :class:`~django.template.Template`.
``context`` ``context``
A dictionary of values to add to the template context. By default, A :class:`dict` of values to add to the template context. By default,
this is an empty dictionary. :class:`~django.template.Context` objects this is an empty dictionary.
are also accepted as ``context`` values. If you pass a
:class:`~django.template.Context` instance or subclass, it will be used
instead of creating a new :class:`~django.template.RequestContext`.
``status`` .. deprecated:: 1.8
The HTTP Status code for the response.
``context`` used to accept a :class:`~django.template.Context`.
``content_type`` ``content_type``
The value included in the HTTP ``Content-Type`` header, including the The value included in the HTTP ``Content-Type`` header, including the
@ -177,6 +217,9 @@ Methods
``content_type`` is specified, then its value is used. Otherwise, ``content_type`` is specified, then its value is used. Otherwise,
:setting:`DEFAULT_CONTENT_TYPE` is used. :setting:`DEFAULT_CONTENT_TYPE` is used.
``status``
The HTTP status code for the response.
``current_app`` ``current_app``
A hint indicating which application contains the current view. See the A hint indicating which application contains the current view. See the
:ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>` :ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`
@ -292,14 +335,13 @@ invoked immediately.
Using TemplateResponse and SimpleTemplateResponse Using TemplateResponse and SimpleTemplateResponse
================================================= =================================================
A TemplateResponse object can be used anywhere that a normal HttpResponse can be A :class:`TemplateResponse` object can be used anywhere that a normal
used. It can also be used as an alternative to calling :class:`django.http.HttpResponse` can be used. It can also be used as an
:func:`~django.shortcuts.render()` or alternative to calling :func:`~django.shortcuts.render()` or
:func:`~django.shortcuts.render_to_response()`. :func:`~django.shortcuts.render_to_response()`.
For example, the following simple view returns a For example, the following simple view returns a :class:`TemplateResponse`
:class:`TemplateResponse()` with a simple template, and a context with a simple template and a context containing a queryset::
containing a queryset::
from django.template.response import TemplateResponse from django.template.response import TemplateResponse

View File

@ -1397,6 +1397,21 @@ Since it's easier to understand with examples, the :ref:`upgrade guide
All this also applies to :func:`~django.template.loader.select_template()`. All this also applies to :func:`~django.template.loader.select_template()`.
:class:`~django.template.Template` and :class:`~django.template.Context` classes in template responses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some methods of :class:`~django.template.response.SimpleTemplateResponse` and
:class:`~django.template.response.TemplateResponse` accepted
:class:`django.template.Context` and :class:`django.template.Template` objects
as arguments. They should now receive :class:`dict` and backend-dependent
template objects respectively.
This also applies to the return types if you have subclassed either template
response class.
Check the :doc:`template response API documentation </ref/template-response>`
for details.
``current_app`` argument of template-related APIs ``current_app`` argument of template-related APIs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

19
tests/cache/tests.py vendored
View File

@ -22,11 +22,11 @@ from django.core.cache import (cache, caches, CacheKeyWarning,
close_caches) close_caches)
from django.db import connection, connections, transaction from django.db import connection, connections, transaction
from django.core.cache.utils import make_template_fragment_key from django.core.cache.utils import make_template_fragment_key
from django.http import HttpResponse, StreamingHttpResponse from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
from django.middleware.cache import (FetchFromCacheMiddleware, from django.middleware.cache import (FetchFromCacheMiddleware,
UpdateCacheMiddleware, CacheMiddleware) UpdateCacheMiddleware, CacheMiddleware)
from django.middleware.csrf import CsrfViewMiddleware from django.middleware.csrf import CsrfViewMiddleware
from django.template import Template from django.template import engines
from django.template.context_processors import csrf from django.template.context_processors import csrf
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.test import (TestCase, TransactionTestCase, RequestFactory, from django.test import (TestCase, TransactionTestCase, RequestFactory,
@ -2022,7 +2022,8 @@ class TestWithTemplateResponse(TestCase):
('Cookie , Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'), ('Cookie , Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
) )
for initial_vary, newheaders, resulting_vary in headers: for initial_vary, newheaders, resulting_vary in headers:
response = TemplateResponse(HttpResponse(), Template("This is a test")) template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
if initial_vary is not None: if initial_vary is not None:
response['Vary'] = initial_vary response['Vary'] = initial_vary
patch_vary_headers(response, newheaders) patch_vary_headers(response, newheaders)
@ -2030,7 +2031,8 @@ class TestWithTemplateResponse(TestCase):
def test_get_cache_key(self): def test_get_cache_key(self):
request = self.factory.get(self.path) request = self.factory.get(self.path)
response = TemplateResponse(HttpResponse(), Template("This is a test")) template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
key_prefix = 'localprefix' key_prefix = 'localprefix'
# Expect None if no headers have been set yet. # Expect None if no headers have been set yet.
self.assertIsNone(get_cache_key(request)) self.assertIsNone(get_cache_key(request))
@ -2052,7 +2054,8 @@ class TestWithTemplateResponse(TestCase):
def test_get_cache_key_with_query(self): def test_get_cache_key_with_query(self):
request = self.factory.get(self.path, {'test': 1}) request = self.factory.get(self.path, {'test': 1})
response = TemplateResponse(HttpResponse(), Template("This is a test")) template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
# Expect None if no headers have been set yet. # Expect None if no headers have been set yet.
self.assertIsNone(get_cache_key(request)) self.assertIsNone(get_cache_key(request))
# Set headers to an empty list. # Set headers to an empty list.
@ -2066,7 +2069,8 @@ class TestWithTemplateResponse(TestCase):
@override_settings(USE_ETAGS=False) @override_settings(USE_ETAGS=False)
def test_without_etag(self): def test_without_etag(self):
response = TemplateResponse(HttpResponse(), Template("This is a test")) template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
self.assertFalse(response.has_header('ETag')) self.assertFalse(response.has_header('ETag'))
patch_response_headers(response) patch_response_headers(response)
self.assertFalse(response.has_header('ETag')) self.assertFalse(response.has_header('ETag'))
@ -2075,7 +2079,8 @@ class TestWithTemplateResponse(TestCase):
@override_settings(USE_ETAGS=True) @override_settings(USE_ETAGS=True)
def test_with_etag(self): def test_with_etag(self):
response = TemplateResponse(HttpResponse(), Template("This is a test")) template = engines['django'].from_string("This is a test")
response = TemplateResponse(HttpRequest(), template)
self.assertFalse(response.has_header('ETag')) self.assertFalse(response.has_header('ETag'))
patch_response_headers(response) patch_response_headers(response)
self.assertFalse(response.has_header('ETag')) self.assertFalse(response.has_header('ETag'))

View File

@ -5,7 +5,7 @@ from django.core.exceptions import MiddlewareNotUsed
from django.core.signals import got_request_exception from django.core.signals import got_request_exception
from django.http import HttpResponse from django.http import HttpResponse
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.template import Template from django.template import engines
from django.test import RequestFactory, TestCase, override_settings from django.test import RequestFactory, TestCase, override_settings
from django.test.utils import patch_logger from django.test.utils import patch_logger
@ -63,7 +63,8 @@ class ResponseMiddleware(TestMiddleware):
class TemplateResponseMiddleware(TestMiddleware): class TemplateResponseMiddleware(TestMiddleware):
def process_template_response(self, request, response): def process_template_response(self, request, response):
super(TemplateResponseMiddleware, self).process_template_response(request, response) super(TemplateResponseMiddleware, self).process_template_response(request, response)
return TemplateResponse(request, Template('Template Response Middleware')) template = engines['django'].from_string('Template Response Middleware')
return TemplateResponse(request, template)
class ExceptionMiddleware(TestMiddleware): class ExceptionMiddleware(TestMiddleware):

View File

@ -1,6 +1,6 @@
from django import http from django import http
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.template import Template from django.template import engines
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
@ -9,11 +9,13 @@ def normal_view(request):
def template_response(request): def template_response(request):
return TemplateResponse(request, Template('OK')) template = engines['django'].from_string('OK')
return TemplateResponse(request, template)
def template_response_error(request): def template_response_error(request):
return TemplateResponse(request, Template('{%')) template = engines['django'].from_string('{%')
return TemplateResponse(request, template)
def not_found(request): def not_found(request):

View File

@ -7,7 +7,7 @@ import time
from django.test import RequestFactory, SimpleTestCase from django.test import RequestFactory, SimpleTestCase
from django.conf import settings from django.conf import settings
from django.template import Template, Context from django.template import Context, engines
from django.template.response import (TemplateResponse, SimpleTemplateResponse, from django.template.response import (TemplateResponse, SimpleTemplateResponse,
ContentNotRenderedError) ContentNotRenderedError)
from django.test import ignore_warnings, override_settings from django.test import ignore_warnings, override_settings
@ -29,7 +29,8 @@ class CustomURLConfMiddleware(object):
class SimpleTemplateResponseTest(SimpleTestCase): class SimpleTemplateResponseTest(SimpleTestCase):
def _response(self, template='foo', *args, **kwargs): def _response(self, template='foo', *args, **kwargs):
return SimpleTemplateResponse(Template(template), *args, **kwargs) template = engines['django'].from_string(template)
return SimpleTemplateResponse(template, *args, **kwargs)
def test_template_resolving(self): def test_template_resolving(self):
response = SimpleTemplateResponse('first/test.html') response = SimpleTemplateResponse('first/test.html')
@ -58,7 +59,8 @@ class SimpleTemplateResponseTest(SimpleTestCase):
self.assertEqual(response.content, b'foo') self.assertEqual(response.content, b'foo')
# rebaking doesn't change the rendered content # rebaking doesn't change the rendered content
response.template_name = Template('bar{{ baz }}') template = engines['django'].from_string('bar{{ baz }}')
response.template_name = template
response.render() response.render()
self.assertEqual(response.content, b'foo') self.assertEqual(response.content, b'foo')
@ -113,6 +115,7 @@ class SimpleTemplateResponseTest(SimpleTestCase):
response.render() response.render()
self.assertEqual(response.content, b'bar') self.assertEqual(response.content, b'bar')
@ignore_warnings(category=RemovedInDjango20Warning)
def test_context_instance(self): def test_context_instance(self):
response = self._response('{{ foo }}{{ processors }}', response = self._response('{{ foo }}{{ processors }}',
Context({'foo': 'bar'})) Context({'foo': 'bar'}))
@ -220,8 +223,9 @@ class TemplateResponseTest(SimpleTestCase):
self.factory = RequestFactory() self.factory = RequestFactory()
def _response(self, template='foo', *args, **kwargs): def _response(self, template='foo', *args, **kwargs):
return TemplateResponse(self.factory.get('/'), Template(template), self._request = self.factory.get('/')
*args, **kwargs) template = engines['django'].from_string(template)
return TemplateResponse(self._request, template, *args, **kwargs)
def test_render(self): def test_render(self):
response = self._response('{{ foo }}{{ processors }}').render() response = self._response('{{ foo }}{{ processors }}').render()
@ -232,6 +236,7 @@ class TemplateResponseTest(SimpleTestCase):
{'foo': 'bar'}).render() {'foo': 'bar'}).render()
self.assertEqual(response.content, b'baryes') self.assertEqual(response.content, b'baryes')
@ignore_warnings(category=RemovedInDjango20Warning)
def test_render_with_context(self): def test_render_with_context(self):
response = self._response('{{ foo }}{{ processors }}', response = self._response('{{ foo }}{{ processors }}',
Context({'foo': 'bar'})).render() Context({'foo': 'bar'})).render()
@ -257,11 +262,8 @@ class TemplateResponseTest(SimpleTestCase):
@ignore_warnings(category=RemovedInDjango20Warning) @ignore_warnings(category=RemovedInDjango20Warning)
def test_custom_app(self): def test_custom_app(self):
response = self._response('{{ foo }}', current_app="foobar") self._response('{{ foo }}', current_app="foobar")
self.assertEqual(self._request.current_app, 'foobar')
rc = response.resolve_context(response.context_data)
self.assertEqual(rc.request.current_app, 'foobar')
def test_pickling(self): def test_pickling(self):
# Create a template response. The context is # Create a template response. The context is

View File

@ -8,7 +8,7 @@ import os
import itertools import itertools
from django.core.urlresolvers import reverse, NoReverseMatch from django.core.urlresolvers import reverse, NoReverseMatch
from django.template import TemplateSyntaxError, Context, Template from django.template import TemplateSyntaxError, Context, engines
from django.test import Client, TestCase, ignore_warnings, override_settings from django.test import Client, TestCase, ignore_warnings, override_settings
from django.test.client import RedirectCycleError, RequestFactory, encode_file from django.test.client import RedirectCycleError, RequestFactory, encode_file
from django.test.utils import ContextList, str_prefix from django.test.utils import ContextList, str_prefix
@ -158,7 +158,8 @@ class AssertContainsTests(TestCase):
without throwing an error. without throwing an error.
Refs #15826. Refs #15826.
""" """
response = SimpleTemplateResponse(Template('Hello'), status=200) template = engines['django'].from_string('Hello')
response = SimpleTemplateResponse(template)
self.assertContains(response, 'Hello') self.assertContains(response, 'Hello')
def test_assert_contains_using_non_template_response(self): def test_assert_contains_using_non_template_response(self):
@ -174,7 +175,8 @@ class AssertContainsTests(TestCase):
without throwing an error. without throwing an error.
Refs #15826. Refs #15826.
""" """
response = SimpleTemplateResponse(Template('Hello'), status=200) template = engines['django'].from_string('Hello')
response = SimpleTemplateResponse(template)
self.assertNotContains(response, 'Bye') self.assertNotContains(response, 'Bye')
def test_assert_not_contains_using_non_template_response(self): def test_assert_not_contains_using_non_template_response(self):

View File

@ -1,5 +1,5 @@
from django.http import HttpResponse from django.http import HttpResponse
from django.template import Template, Context from django.template import engines
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
from django.utils.decorators import decorator_from_middleware from django.utils.decorators import decorator_from_middleware
@ -70,8 +70,8 @@ class DecoratorFromMiddlewareTests(TestCase):
@full_dec @full_dec
def normal_view(request): def normal_view(request):
t = Template("Hello world") template = engines['django'].from_string("Hello world")
return HttpResponse(t.render(Context({}))) return HttpResponse(template.render())
request = self.rf.get('/') request = self.rf.get('/')
normal_view(request) normal_view(request)
@ -89,8 +89,8 @@ class DecoratorFromMiddlewareTests(TestCase):
@full_dec @full_dec
def template_response_view(request): def template_response_view(request):
t = Template("Hello world") template = engines['django'].from_string("Hello world")
return TemplateResponse(request, t, {}) return TemplateResponse(request, template)
request = self.rf.get('/') request = self.rf.get('/')
response = template_response_view(request) response = template_response_view(request)