Removed dictionary and context_instance parameters for render functions.

Per deprecation timeline.
This commit is contained in:
Tim Graham 2015-09-03 22:01:30 -04:00
parent b3641512c8
commit 9023696613
11 changed files with 29 additions and 256 deletions

View File

@ -10,63 +10,27 @@ from django.db.models.query import QuerySet
from django.http import ( from django.http import (
Http404, HttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect, Http404, HttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect,
) )
from django.template import RequestContext, loader from django.template import loader
from django.template.engine import (
_context_instance_undefined, _dictionary_undefined
)
from django.utils import six from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import Promise from django.utils.functional import Promise
def render_to_response(template_name, context=None, def render_to_response(template_name, context=None, content_type=None, status=None, using=None):
context_instance=_context_instance_undefined,
content_type=None, status=None,
dictionary=_dictionary_undefined, using=None):
""" """
Returns a HttpResponse whose content is filled with the result of calling Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments. django.template.loader.render_to_string() with the passed arguments.
""" """
if (context_instance is _context_instance_undefined content = loader.render_to_string(template_name, context, using=using)
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
content = loader.render_to_string(template_name, context, using=using)
else:
# Some deprecated arguments were passed - use the legacy code path
content = loader.render_to_string(
template_name, context, context_instance, dictionary,
using=using)
return HttpResponse(content, content_type, status) return HttpResponse(content, content_type, status)
def render(request, template_name, context=None, def render(request, template_name, context=None, content_type=None, status=None, using=None):
context_instance=_context_instance_undefined,
content_type=None, status=None,
dictionary=_dictionary_undefined,
using=None):
""" """
Returns a HttpResponse whose content is filled with the result of calling Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments. django.template.loader.render_to_string() with the passed arguments.
Uses a RequestContext by default.
""" """
if (context_instance is _context_instance_undefined content = loader.render_to_string(template_name, context, request, using=using)
and dictionary is _dictionary_undefined):
# No deprecated arguments were passed - use the new code path
# In Django 1.10, request should become a positional argument.
content = loader.render_to_string(
template_name, context, request=request, using=using)
else:
# Some deprecated arguments were passed - use the legacy code path
if context_instance is not _context_instance_undefined:
pass
else:
context_instance = RequestContext(request)
content = loader.render_to_string(
template_name, context, context_instance, dictionary,
using=using)
return HttpResponse(content, content_type, status) return HttpResponse(content, content_type, status)

View File

@ -11,9 +11,6 @@ from .context import _builtin_context_processors
from .exceptions import TemplateDoesNotExist from .exceptions import TemplateDoesNotExist
from .library import import_library from .library import import_library
_context_instance_undefined = object()
_dictionary_undefined = object()
class Engine(object): class Engine(object):
default_builtins = [ default_builtins = [
@ -183,40 +180,17 @@ class Engine(object):
# will be removed in Django 1.10. It's superseded by a new render_to_string # will be removed in Django 1.10. It's superseded by a new render_to_string
# function in django.template.loader. # function in django.template.loader.
def render_to_string(self, template_name, context=None, def render_to_string(self, template_name, context=None):
context_instance=_context_instance_undefined,
dictionary=_dictionary_undefined):
if context_instance is _context_instance_undefined:
context_instance = None
else:
warnings.warn(
"The context_instance argument of render_to_string is "
"deprecated.", RemovedInDjango110Warning, stacklevel=2)
if dictionary is _dictionary_undefined:
dictionary = None
else:
warnings.warn(
"The dictionary argument of render_to_string was renamed to "
"context.", RemovedInDjango110Warning, stacklevel=2)
context = dictionary
if isinstance(template_name, (list, tuple)): if isinstance(template_name, (list, tuple)):
t = self.select_template(template_name) t = self.select_template(template_name)
else: else:
t = self.get_template(template_name) t = self.get_template(template_name)
if not context_instance: # Django < 1.8 accepted a Context in `context` even though that's
# Django < 1.8 accepted a Context in `context` even though that's # unintended. Preserve this ability but don't rewrap `context`.
# unintended. Preserve this ability but don't rewrap `context`. if isinstance(context, Context):
if isinstance(context, Context): return t.render(context)
return t.render(context) else:
else: return t.render(Context(context))
return t.render(Context(context))
if not context:
return t.render(context_instance)
# Add the context to the context stack, ensuring it gets removed again
# to keep the context_instance in the same state it started in.
with context_instance.push(context):
return t.render(context_instance)
def select_template(self, template_name_list): def select_template(self, template_name_list):
""" """

View File

@ -3,8 +3,6 @@ import warnings
from django.utils.deprecation import RemovedInDjango110Warning from django.utils.deprecation import RemovedInDjango110Warning
from . import engines from . import engines
from .backends.django import DjangoTemplates
from .engine import _context_instance_undefined, _dictionary_undefined
from .exceptions import TemplateDoesNotExist from .exceptions import TemplateDoesNotExist
from .loaders import base from .loaders import base
@ -49,60 +47,17 @@ def select_template(template_name_list, using=None):
raise TemplateDoesNotExist("No template names provided") raise TemplateDoesNotExist("No template names provided")
def render_to_string(template_name, context=None, def render_to_string(template_name, context=None, request=None, using=None):
context_instance=_context_instance_undefined,
dictionary=_dictionary_undefined,
request=None, using=None):
""" """
Loads a template and renders it with a context. Returns a string. Loads a template and renders it with a context. Returns a string.
template_name may be a string or a list of strings. template_name may be a string or a list of strings.
""" """
if (context_instance is _context_instance_undefined if isinstance(template_name, (list, tuple)):
and dictionary is _dictionary_undefined): template = select_template(template_name, using=using)
# No deprecated arguments were passed - use the new code path
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=using)
else:
template = get_template(template_name, using=using)
return template.render(context, request)
else: else:
chain = [] template = get_template(template_name, using=using)
# Some deprecated arguments were passed - use the legacy code path return template.render(context, request)
for engine in _engine_list(using):
try:
# This is required for deprecating properly arguments specific
# to Django templates. Remove Engine.render_to_string() at the
# same time as this code path in Django 1.10.
if isinstance(engine, DjangoTemplates):
if request is not None:
raise ValueError(
"render_to_string doesn't support the request argument "
"when some deprecated arguments are passed.")
# Hack -- use the internal Engine instance of DjangoTemplates.
return engine.engine.render_to_string(
template_name, context, context_instance, dictionary)
elif context_instance is not _context_instance_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the context_instance argument." %
engine.name, stacklevel=2)
elif dictionary is not _dictionary_undefined:
warnings.warn(
"Skipping template backend %s because its render_to_string "
"method doesn't support the dictionary argument." %
engine.name, stacklevel=2)
except TemplateDoesNotExist as e:
chain.append(e)
continue
if template_name:
if isinstance(template_name, (list, tuple)):
template_name = ', '.join(template_name)
raise TemplateDoesNotExist(template_name, chain=chain)
else:
raise TemplateDoesNotExist("No template names provided")
def _engine_list(using=None): def _engine_list(using=None):

View File

@ -15,14 +15,13 @@ introduce controlled coupling for convenience's sake.
``render`` ``render``
========== ==========
.. function:: render(request, template_name, context=None, context_instance=_context_instance_undefined, content_type=None, status=None, using=None) .. function:: render(request, template_name, context=None, content_type=None, status=None, using=None)
Combines a given template with a given context dictionary and returns an Combines a given template with a given context dictionary and returns an
:class:`~django.http.HttpResponse` object with that rendered text. :class:`~django.http.HttpResponse` object with that rendered text.
:func:`render()` is the same as a call to :func:`render()` is the same as a call to :func:`render_to_response()` but
:func:`render_to_response()` with a ``context_instance`` argument that it also makes the current request available in the template.
forces the use of a :class:`~django.template.RequestContext`.
Django does not provide a shortcut function which returns a Django does not provide a shortcut function which returns a
:class:`~django.template.response.TemplateResponse` because the constructor :class:`~django.template.response.TemplateResponse` because the constructor
@ -46,20 +45,6 @@ Optional arguments
is an empty dictionary. If a value in the dictionary is callable, the is an empty dictionary. If a value in the dictionary is callable, the
view will call it just before rendering the template. view will call it just before rendering the template.
.. versionchanged:: 1.8
The ``context`` argument used to be called ``dictionary``. That name
is deprecated in Django 1.8 and will be removed in Django 1.10.
``context_instance``
The context instance to render the template with. By default, the template
will be rendered with a ``RequestContext`` instance (filled with values from
``request`` and ``context``).
.. deprecated:: 1.8
The ``context_instance`` argument is deprecated. Simply use ``context``.
``content_type`` ``content_type``
The MIME type to use for the resulting document. Defaults to the value of The MIME type to use for the resulting document. Defaults to the value of
the :setting:`DEFAULT_CONTENT_TYPE` setting. the :setting:`DEFAULT_CONTENT_TYPE` setting.
@ -103,7 +88,7 @@ This example is equivalent to::
``render_to_response`` ``render_to_response``
====================== ======================
.. function:: render_to_response(template_name, context=None, context_instance=_context_instance_undefined, content_type=None, status=None, using=None) .. function:: render_to_response(template_name, context=None, content_type=None, status=None, using=None)
Renders a given template with a given context dictionary and returns an Renders a given template with a given context dictionary and returns an
:class:`~django.http.HttpResponse` object with that rendered text. :class:`~django.http.HttpResponse` object with that rendered text.
@ -125,27 +110,6 @@ Optional arguments
is an empty dictionary. If a value in the dictionary is callable, the is an empty dictionary. If a value in the dictionary is callable, the
view will call it just before rendering the template. view will call it just before rendering the template.
.. versionchanged:: 1.8
The ``context`` argument used to be called ``dictionary``. That name
is deprecated in Django 1.8 and will be removed in Django 1.10.
``context_instance``
The context instance to render the template with. By default, the template
will be rendered with a :class:`~django.template.Context` instance (filled
with values from ``context``). If you need to use :ref:`context
processors <subclassing-context-requestcontext>`, render the template with
a :class:`~django.template.RequestContext` instance instead. Your code
might look something like this::
return render_to_response('my_template.html',
my_context,
context_instance=RequestContext(request))
.. deprecated:: 1.8
The ``context_instance`` argument is deprecated. Simply use ``context``.
``content_type`` ``content_type``
The MIME type to use for the resulting document. Defaults to the value of The MIME type to use for the resulting document. Defaults to the value of
the :setting:`DEFAULT_CONTENT_TYPE` setting. the :setting:`DEFAULT_CONTENT_TYPE` setting.

View File

@ -261,7 +261,7 @@ the following templates:
In addition, to cut down on the repetitive nature of loading and rendering In addition, to cut down on the repetitive nature of loading and rendering
templates, Django provides a shortcut function which automates the process. templates, Django provides a shortcut function which automates the process.
.. function:: render_to_string(template_name, context=None, context_instance=_context_instance_undefined, request=None, using=None) .. function:: render_to_string(template_name, context=None, request=None, using=None)
``render_to_string()`` loads a template like :func:`get_template` and ``render_to_string()`` loads a template like :func:`get_template` and
calls its ``render()`` method immediately. It takes the following calls its ``render()`` method immediately. It takes the following
@ -275,24 +275,6 @@ templates, Django provides a shortcut function which automates the process.
``context`` ``context``
A :class:`dict` to be used as the template's context for rendering. A :class:`dict` to be used as the template's context for rendering.
.. versionchanged:: 1.8
The ``context`` argument used to be called ``dictionary``. That name
is deprecated in Django 1.8 and will be removed in Django 1.10.
``context`` is now optional. An empty context will be used if it
isn't provided.
``context_instance``
An instance of :class:`~django.template.Context` or a subclass (e.g., an
instance of :class:`~django.template.RequestContext`) to use as the
template's context.
.. deprecated:: 1.8
The ``context_instance`` argument is deprecated. Use ``context`` and
if needed ``request``.
``request`` ``request``
An optional :class:`~django.http.HttpRequest` that will be available An optional :class:`~django.http.HttpRequest` that will be available
during the template's rendering process. during the template's rendering process.

View File

@ -19,13 +19,6 @@ class ShortcutTests(SimpleTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR..\n') self.assertEqual(response.content, b'FOO.BAR..\n')
@ignore_warnings(category=RemovedInDjango110Warning)
def test_render_to_response_with_request_context(self):
response = self.client.get('/render_to_response/request_context/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR../render_to_response/request_context/\n')
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8')
def test_render_to_response_with_content_type(self): def test_render_to_response_with_content_type(self):
response = self.client.get('/render_to_response/content_type/') response = self.client.get('/render_to_response/content_type/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -68,13 +61,6 @@ class ShortcutTests(SimpleTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR../render/multiple_templates/\n') self.assertEqual(response.content, b'FOO.BAR../render/multiple_templates/\n')
@ignore_warnings(category=RemovedInDjango110Warning)
def test_render_with_base_context(self):
response = self.client.get('/render/base_context/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'FOO.BAR..\n')
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8')
def test_render_with_content_type(self): def test_render_with_content_type(self):
response = self.client.get('/render/content_type/') response = self.client.get('/render/content_type/')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@ -5,14 +5,12 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^render_to_response/$', views.render_to_response_view), url(r'^render_to_response/$', views.render_to_response_view),
url(r'^render_to_response/multiple_templates/$', views.render_to_response_view_with_multiple_templates), url(r'^render_to_response/multiple_templates/$', views.render_to_response_view_with_multiple_templates),
url(r'^render_to_response/request_context/$', views.render_to_response_view_with_request_context),
url(r'^render_to_response/content_type/$', views.render_to_response_view_with_content_type), url(r'^render_to_response/content_type/$', views.render_to_response_view_with_content_type),
url(r'^render_to_response/status/$', views.render_to_response_view_with_status), url(r'^render_to_response/status/$', views.render_to_response_view_with_status),
url(r'^render_to_response/using/$', views.render_to_response_view_with_using), url(r'^render_to_response/using/$', views.render_to_response_view_with_using),
url(r'^render_to_response/context_instance_misuse/$', views.render_to_response_with_context_instance_misuse), url(r'^render_to_response/context_instance_misuse/$', views.render_to_response_with_context_instance_misuse),
url(r'^render/$', views.render_view), url(r'^render/$', views.render_view),
url(r'^render/multiple_templates/$', views.render_view_with_multiple_templates), url(r'^render/multiple_templates/$', views.render_view_with_multiple_templates),
url(r'^render/base_context/$', views.render_view_with_base_context),
url(r'^render/content_type/$', views.render_view_with_content_type), url(r'^render/content_type/$', views.render_view_with_content_type),
url(r'^render/status/$', views.render_view_with_status), url(r'^render/status/$', views.render_view_with_status),
url(r'^render/using/$', views.render_view_with_using), url(r'^render/using/$', views.render_view_with_using),

View File

@ -1,5 +1,5 @@
from django.shortcuts import render, render_to_response from django.shortcuts import render, render_to_response
from django.template import Context, RequestContext from django.template import RequestContext
def render_to_response_view(request): def render_to_response_view(request):
@ -19,13 +19,6 @@ def render_to_response_view_with_multiple_templates(request):
}) })
def render_to_response_view_with_request_context(request):
return render_to_response('shortcuts/render_test.html', {
'foo': 'FOO',
'bar': 'BAR',
}, context_instance=RequestContext(request))
def render_to_response_view_with_content_type(request): def render_to_response_view_with_content_type(request):
return render_to_response('shortcuts/render_test.html', { return render_to_response('shortcuts/render_test.html', {
'foo': 'FOO', 'foo': 'FOO',
@ -72,13 +65,6 @@ def render_view_with_multiple_templates(request):
}) })
def render_view_with_base_context(request):
return render(request, 'shortcuts/render_test.html', {
'foo': 'FOO',
'bar': 'BAR',
}, context_instance=Context())
def render_view_with_content_type(request): def render_view_with_content_type(request):
return render(request, 'shortcuts/render_test.html', { return render(request, 'shortcuts/render_test.html', {
'foo': 'FOO', 'foo': 'FOO',

View File

@ -2,22 +2,17 @@ import os
from django.template import Context from django.template import Context
from django.template.engine import Engine from django.template.engine import Engine
from django.test import SimpleTestCase, ignore_warnings from django.test import SimpleTestCase
from django.utils.deprecation import RemovedInDjango110Warning
from .utils import ROOT, TEMPLATE_DIR from .utils import ROOT, TEMPLATE_DIR
OTHER_DIR = os.path.join(ROOT, 'other_templates') OTHER_DIR = os.path.join(ROOT, 'other_templates')
@ignore_warnings(category=RemovedInDjango110Warning) class RenderToStringTest(SimpleTestCase):
class DeprecatedRenderToStringTest(SimpleTestCase):
def setUp(self): def setUp(self):
self.engine = Engine( self.engine = Engine(dirs=[TEMPLATE_DIR])
dirs=[TEMPLATE_DIR],
libraries={'custom': 'template_tests.templatetags.custom'},
)
def test_basic_context(self): def test_basic_context(self):
self.assertEqual( self.assertEqual(
@ -25,33 +20,6 @@ class DeprecatedRenderToStringTest(SimpleTestCase):
'obj:test\n', 'obj:test\n',
) )
def test_existing_context_kept_clean(self):
context = Context({'obj': 'before'})
output = self.engine.render_to_string(
'test_context.html', {'obj': 'after'}, context_instance=context,
)
self.assertEqual(output, 'obj:after\n')
self.assertEqual(context['obj'], 'before')
def test_no_empty_dict_pushed_to_stack(self):
"""
#21741 -- An empty dict should not be pushed to the context stack when
render_to_string is called without a context argument.
"""
# The stack should have a length of 1, corresponding to the builtins
self.assertEqual(
'1',
self.engine.render_to_string('test_context_stack.html').strip(),
)
self.assertEqual(
'1',
self.engine.render_to_string(
'test_context_stack.html',
context_instance=Context()
).strip(),
)
class LoaderTests(SimpleTestCase): class LoaderTests(SimpleTestCase):

View File

@ -20,9 +20,7 @@ from django.test import (
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
from django.utils._os import upath from django.utils._os import upath
from django.utils.deprecation import ( from django.utils.deprecation import RemovedInDjango20Warning
RemovedInDjango20Warning, RemovedInDjango110Warning,
)
from django.utils.translation import ugettext_lazy from django.utils.translation import ugettext_lazy
from .models import CustomUser from .models import CustomUser
@ -1064,7 +1062,6 @@ class ContextTests(TestDataMixin, TestCase):
'python', 'dolly'}, 'python', 'dolly'},
l.keys()) l.keys())
@ignore_warnings(category=RemovedInDjango110Warning)
def test_15368(self): def test_15368(self):
# Need to insert a context processor that assumes certain things about # Need to insert a context processor that assumes certain things about
# the request instance. This triggers a bug caused by some ways of # the request instance. This triggers a bug caused by some ways of

View File

@ -4,8 +4,7 @@ from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render_to_response from django.shortcuts import render, render_to_response
from django.template import RequestContext
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.test import Client from django.test import Client
from django.test.client import CONTENT_TYPE_RE from django.test.client import CONTENT_TYPE_RE
@ -152,7 +151,7 @@ def read_buffer(request):
def request_context_view(request): def request_context_view(request):
# Special attribute that won't be present on a plain HttpRequest # Special attribute that won't be present on a plain HttpRequest
request.special_path = request.path request.special_path = request.path
return render_to_response('request_context.html', context_instance=RequestContext(request, {})) return render(request, 'request_context.html')
def render_template_multiple_times(request): def render_template_multiple_times(request):