From 79deb6a0716e554cac5308e86f5754f19ad436dc Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Fri, 9 Jan 2015 22:59:00 +0100 Subject: [PATCH] Accounted for multiple template engines in template responses. --- django/contrib/messages/tests/urls.py | 9 +- django/template/response.py | 93 +++++++++++------- docs/internals/deprecation.txt | 5 + docs/ref/template-response.txt | 132 +++++++++++++++++--------- docs/releases/1.8.txt | 15 +++ tests/cache/tests.py | 19 ++-- tests/middleware_exceptions/tests.py | 5 +- tests/middleware_exceptions/views.py | 8 +- tests/template_tests/test_response.py | 22 +++-- tests/test_client_regress/tests.py | 8 +- tests/utils_tests/test_decorators.py | 10 +- 11 files changed, 215 insertions(+), 111 deletions(-) diff --git a/django/contrib/messages/tests/urls.py b/django/contrib/messages/tests/urls.py index 2055d4f3274..43cc6063cb4 100644 --- a/django/contrib/messages/tests/urls.py +++ b/django/contrib/messages/tests/urls.py @@ -3,7 +3,7 @@ from django.contrib import messages from django.core.urlresolvers import reverse from django import forms 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.views.decorators.cache import never_cache from django.contrib.messages.views import SuccessMessageMixin @@ -48,13 +48,14 @@ def add_template_response(request, message_type): @never_cache def show(request): - t = Template(TEMPLATE) - return HttpResponse(t.render(RequestContext(request))) + template = engines['django'].from_string(TEMPLATE) + return HttpResponse(template.render(request=request)) @never_cache def show_template_response(request): - return TemplateResponse(request, Template(TEMPLATE)) + template = engines['django'].from_string(TEMPLATE) + return TemplateResponse(request, template) class ContactForm(forms.Form): diff --git a/django/template/response.py b/django/template/response.py index 8f175b14e61..ab9559853af 100644 --- a/django/template/response.py +++ b/django/template/response.py @@ -1,7 +1,8 @@ import warnings 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.utils import six from django.utils.deprecation import RemovedInDjango20Warning @@ -16,14 +17,30 @@ class SimpleTemplateResponse(HttpResponse): def __init__(self, template, context=None, content_type=None, status=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 # '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.context_data = context 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 # with rendered template so we always pass empty string in order to # prevent errors and provide shorter signature. @@ -62,14 +79,45 @@ class SimpleTemplateResponse(HttpResponse): else: 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): - """Converts 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) + return context + + def _resolve_context(self, context): + # This wrapper deprecates returning a Context or a RequestContext in + # subclasses that override resolve_context. It can be removed in + # Django 2.0. If returning a Context or a RequestContext works by + # 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 def rendered_content(self): @@ -80,14 +128,9 @@ class SimpleTemplateResponse(HttpResponse): 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) - # TODO - remove this hack - makes the tests pass until the next commit - try: - template = template.template - except AttributeError: - pass - content = template.render(context) + template = self._resolve_template(self.template_name) + context = self._resolve_context(self.context_data) + content = template.render(context, self._request) return content def add_post_render_callback(self, callback): @@ -147,10 +190,6 @@ class TemplateResponse(SimpleTemplateResponse): def __init__(self, request, template, context=None, content_type=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 # having to avoid needing to create the RequestContext directly if current_app is not _current_app_undefined: @@ -161,14 +200,4 @@ class TemplateResponse(SimpleTemplateResponse): request.current_app = current_app super(TemplateResponse, self).__init__( template, context, content_type, status, charset) - - 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 + self._request = request diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index e9161e7254e..4e03378f06d 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -114,6 +114,11 @@ details on these changes. :class:`~django.template.Context` in their :meth:`~django.template.backends.base.Template.render()` method anymore. +* :doc:`Template response APIs ` 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 removed: diff --git a/docs/ref/template-response.txt b/docs/ref/template-response.txt index 3f7572b557d..c1ae0267a53 100644 --- a/docs/ref/template-response.txt +++ b/docs/ref/template-response.txt @@ -31,19 +31,28 @@ Attributes .. attribute:: SimpleTemplateResponse.template_name - The name of the template to be rendered. Accepts a - :class:`~django.template.Template` object, a path to a template or list - of template paths. + The name of the template to be rendered. Accepts a backend-dependent + template object (such as those returned by + :func:`~django.template.loader.get_template()`), the name of a template, + or a list of template names. Example: ``['foo.html', 'path/to/bar.html']`` + .. deprecated:: 1.8 + + ``template_name`` used to accept a :class:`~django.template.Template`. + .. attribute:: SimpleTemplateResponse.context_data - The context data to be used when rendering the template. It can be - a dictionary or a context object. + The context data to be used when rendering the template. It must be a + :class:`dict`. Example: ``{'foo': 123}`` + .. deprecated:: 1.8 + + ``context_data`` used to accept a :class:`~django.template.Context`. + .. attribute:: SimpleTemplateResponse.rendered_content 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) - Instantiates a - :class:`~django.template.response.SimpleTemplateResponse` object - with the given template, context, content type, and HTTP status. + Instantiates a :class:`~django.template.response.SimpleTemplateResponse` + object with the given template, context, content type, HTTP status, and + charset. ``template`` - The full name of a template, or a sequence of template names. - :class:`~django.template.Template` instances can also be used. + A backend-dependent template object (such as those returned by + :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`` - 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. + A :class:`dict` of values to add to the template context. By default, + this is an empty dictionary. - ``status`` - The HTTP Status code for the response. + .. deprecated:: 1.8 + + ``context`` used to accept a :class:`~django.template.Context`. ``content_type`` 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, :setting:`DEFAULT_CONTENT_TYPE` is used. + ``status`` + The HTTP status code for the response. + ``charset`` 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 @@ -91,22 +108,42 @@ Methods .. 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. + Preprocesses context data that will be used for rendering a template. + Accepts a :class:`dict` of context data. By default, returns the same + :class:`dict`. - 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) 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. + backend-dependent template object (such as those returned by + :func:`~django.template.loader.get_template()`), the name of a template, + or a list of template names. - 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() @@ -142,34 +179,37 @@ TemplateResponse objects .. class:: TemplateResponse() ``TemplateResponse`` is a subclass of - :class:`~django.template.response.SimpleTemplateResponse` that uses - a :class:`~django.template.RequestContext` instead of - a :class:`~django.template.Context`. + :class:`~django.template.response.SimpleTemplateResponse` that knows about + the current :class:`~django.http.HttpRequest`. Methods ------- .. method:: TemplateResponse.__init__(request, template, context=None, content_type=None, status=None, current_app=None, charset=None) - Instantiates an ``TemplateResponse`` object with the given - template, context, MIME type and HTTP status. + Instantiates a :class:`~django.template.response.TemplateResponse` object + with the given request, template, context, content type, HTTP status, and + charset. ``request`` An :class:`~django.http.HttpRequest` instance. ``template`` - The full name of a template, or a sequence of template names. - :class:`~django.template.Template` instances can also be used. + A backend-dependent template object (such as those returned by + :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`` - 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. If you pass a - :class:`~django.template.Context` instance or subclass, it will be used - instead of creating a new :class:`~django.template.RequestContext`. + A :class:`dict` of values to add to the template context. By default, + this is an empty dictionary. - ``status`` - The HTTP Status code for the response. + .. deprecated:: 1.8 + + ``context`` used to accept a :class:`~django.template.Context`. ``content_type`` 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, :setting:`DEFAULT_CONTENT_TYPE` is used. + ``status`` + The HTTP status code for the response. + ``current_app`` A hint indicating which application contains the current view. See the :ref:`namespaced URL resolution strategy ` @@ -292,14 +335,13 @@ invoked immediately. 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 -:func:`~django.shortcuts.render()` or +A :class:`TemplateResponse` object can be used anywhere that a normal +:class:`django.http.HttpResponse` can be used. It can also be used as an +alternative to calling :func:`~django.shortcuts.render()` or :func:`~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:: +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 diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 4c3b398cd14..a07a2093473 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -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()`. +: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 ` +for details. + ``current_app`` argument of template-related APIs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 95cf2675b23..3e2dc5c1a04 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -22,11 +22,11 @@ from django.core.cache import (cache, caches, CacheKeyWarning, close_caches) from django.db import connection, connections, transaction 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, UpdateCacheMiddleware, CacheMiddleware) 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.response import TemplateResponse from django.test import (TestCase, TransactionTestCase, RequestFactory, @@ -2022,7 +2022,8 @@ class TestWithTemplateResponse(TestCase): ('Cookie , Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'), ) 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: response['Vary'] = initial_vary patch_vary_headers(response, newheaders) @@ -2030,7 +2031,8 @@ class TestWithTemplateResponse(TestCase): def test_get_cache_key(self): 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' # Expect None if no headers have been set yet. self.assertIsNone(get_cache_key(request)) @@ -2052,7 +2054,8 @@ class TestWithTemplateResponse(TestCase): def test_get_cache_key_with_query(self): 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. self.assertIsNone(get_cache_key(request)) # Set headers to an empty list. @@ -2066,7 +2069,8 @@ class TestWithTemplateResponse(TestCase): @override_settings(USE_ETAGS=False) 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')) patch_response_headers(response) self.assertFalse(response.has_header('ETag')) @@ -2075,7 +2079,8 @@ class TestWithTemplateResponse(TestCase): @override_settings(USE_ETAGS=True) 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')) patch_response_headers(response) self.assertFalse(response.has_header('ETag')) diff --git a/tests/middleware_exceptions/tests.py b/tests/middleware_exceptions/tests.py index 8a2ddfa4a13..8c191e4ea5f 100644 --- a/tests/middleware_exceptions/tests.py +++ b/tests/middleware_exceptions/tests.py @@ -5,7 +5,7 @@ from django.core.exceptions import MiddlewareNotUsed 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.template import engines from django.test import RequestFactory, TestCase, override_settings from django.test.utils import patch_logger @@ -63,7 +63,8 @@ class ResponseMiddleware(TestMiddleware): 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')) + template = engines['django'].from_string('Template Response Middleware') + return TemplateResponse(request, template) class ExceptionMiddleware(TestMiddleware): diff --git a/tests/middleware_exceptions/views.py b/tests/middleware_exceptions/views.py index 59abe26bff0..d3d7fae6617 100644 --- a/tests/middleware_exceptions/views.py +++ b/tests/middleware_exceptions/views.py @@ -1,6 +1,6 @@ from django import http from django.core.exceptions import PermissionDenied -from django.template import Template +from django.template import engines from django.template.response import TemplateResponse @@ -9,11 +9,13 @@ def normal_view(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): - return TemplateResponse(request, Template('{%')) + template = engines['django'].from_string('{%') + return TemplateResponse(request, template) def not_found(request): diff --git a/tests/template_tests/test_response.py b/tests/template_tests/test_response.py index c96eb8ff37f..993b2002c86 100644 --- a/tests/template_tests/test_response.py +++ b/tests/template_tests/test_response.py @@ -7,7 +7,7 @@ import time from django.test import RequestFactory, SimpleTestCase from django.conf import settings -from django.template import Template, Context +from django.template import Context, engines from django.template.response import (TemplateResponse, SimpleTemplateResponse, ContentNotRenderedError) from django.test import ignore_warnings, override_settings @@ -29,7 +29,8 @@ class CustomURLConfMiddleware(object): class SimpleTemplateResponseTest(SimpleTestCase): 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): response = SimpleTemplateResponse('first/test.html') @@ -58,7 +59,8 @@ class SimpleTemplateResponseTest(SimpleTestCase): self.assertEqual(response.content, b'foo') # 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() self.assertEqual(response.content, b'foo') @@ -113,6 +115,7 @@ class SimpleTemplateResponseTest(SimpleTestCase): response.render() self.assertEqual(response.content, b'bar') + @ignore_warnings(category=RemovedInDjango20Warning) def test_context_instance(self): response = self._response('{{ foo }}{{ processors }}', Context({'foo': 'bar'})) @@ -220,8 +223,9 @@ class TemplateResponseTest(SimpleTestCase): self.factory = RequestFactory() def _response(self, template='foo', *args, **kwargs): - return TemplateResponse(self.factory.get('/'), Template(template), - *args, **kwargs) + self._request = self.factory.get('/') + template = engines['django'].from_string(template) + return TemplateResponse(self._request, template, *args, **kwargs) def test_render(self): response = self._response('{{ foo }}{{ processors }}').render() @@ -232,6 +236,7 @@ class TemplateResponseTest(SimpleTestCase): {'foo': 'bar'}).render() self.assertEqual(response.content, b'baryes') + @ignore_warnings(category=RemovedInDjango20Warning) def test_render_with_context(self): response = self._response('{{ foo }}{{ processors }}', Context({'foo': 'bar'})).render() @@ -257,11 +262,8 @@ class TemplateResponseTest(SimpleTestCase): @ignore_warnings(category=RemovedInDjango20Warning) def test_custom_app(self): - response = self._response('{{ foo }}', current_app="foobar") - - rc = response.resolve_context(response.context_data) - - self.assertEqual(rc.request.current_app, 'foobar') + self._response('{{ foo }}', current_app="foobar") + self.assertEqual(self._request.current_app, 'foobar') def test_pickling(self): # Create a template response. The context is diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py index 6f8d97c8861..e17bf4ef811 100644 --- a/tests/test_client_regress/tests.py +++ b/tests/test_client_regress/tests.py @@ -8,7 +8,7 @@ import os import itertools 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.client import RedirectCycleError, RequestFactory, encode_file from django.test.utils import ContextList, str_prefix @@ -158,7 +158,8 @@ class AssertContainsTests(TestCase): without throwing an error. Refs #15826. """ - response = SimpleTemplateResponse(Template('Hello'), status=200) + template = engines['django'].from_string('Hello') + response = SimpleTemplateResponse(template) self.assertContains(response, 'Hello') def test_assert_contains_using_non_template_response(self): @@ -174,7 +175,8 @@ class AssertContainsTests(TestCase): without throwing an error. Refs #15826. """ - response = SimpleTemplateResponse(Template('Hello'), status=200) + template = engines['django'].from_string('Hello') + response = SimpleTemplateResponse(template) self.assertNotContains(response, 'Bye') def test_assert_not_contains_using_non_template_response(self): diff --git a/tests/utils_tests/test_decorators.py b/tests/utils_tests/test_decorators.py index a05a736c30d..8ef4737e544 100644 --- a/tests/utils_tests/test_decorators.py +++ b/tests/utils_tests/test_decorators.py @@ -1,5 +1,5 @@ from django.http import HttpResponse -from django.template import Template, Context +from django.template import engines from django.template.response import TemplateResponse from django.test import TestCase, RequestFactory from django.utils.decorators import decorator_from_middleware @@ -70,8 +70,8 @@ class DecoratorFromMiddlewareTests(TestCase): @full_dec def normal_view(request): - t = Template("Hello world") - return HttpResponse(t.render(Context({}))) + template = engines['django'].from_string("Hello world") + return HttpResponse(template.render()) request = self.rf.get('/') normal_view(request) @@ -89,8 +89,8 @@ class DecoratorFromMiddlewareTests(TestCase): @full_dec def template_response_view(request): - t = Template("Hello world") - return TemplateResponse(request, t, {}) + template = engines['django'].from_string("Hello world") + return TemplateResponse(request, template) request = self.rf.get('/') response = template_response_view(request)