Fixed #27258 -- Prohibited django.Template.render() with non-dict context.

Thanks Shivang Bharadwaj for the initial patch.
This commit is contained in:
Shivang Bharadwaj 2016-12-29 02:33:20 +05:30 committed by Tim Graham
parent 4e89082f31
commit 6a74950513
4 changed files with 33 additions and 3 deletions

View File

@ -281,6 +281,8 @@ def make_context(context, request=None, **kwargs):
""" """
Create a suitable Context from a plain dict and optionally an HttpRequest. Create a suitable Context from a plain dict and optionally an HttpRequest.
""" """
if context is not None and not isinstance(context, dict):
raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
if request is None: if request is None:
context = Context(context, **kwargs) context = Context(context, **kwargs)
else: else:

View File

@ -105,7 +105,7 @@ def csrf_failure(request, reason="", template_name=CSRF_FAILURE_TEMPLATE_NAME):
Default view used when request fails CSRF protection Default view used when request fails CSRF protection
""" """
from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
c = Context({ c = {
'title': _("Forbidden"), 'title': _("Forbidden"),
'main': _("CSRF verification failed. Request aborted."), 'main': _("CSRF verification failed. Request aborted."),
'reason': reason, 'reason': reason,
@ -132,13 +132,14 @@ def csrf_failure(request, reason="", template_name=CSRF_FAILURE_TEMPLATE_NAME):
'DEBUG': settings.DEBUG, 'DEBUG': settings.DEBUG,
'docs_version': get_docs_version(), 'docs_version': get_docs_version(),
'more': _("More information is available with DEBUG=True."), 'more': _("More information is available with DEBUG=True."),
}) }
try: try:
t = loader.get_template(template_name) t = loader.get_template(template_name)
except TemplateDoesNotExist: except TemplateDoesNotExist:
if template_name == CSRF_FAILURE_TEMPLATE_NAME: if template_name == CSRF_FAILURE_TEMPLATE_NAME:
# If the default template doesn't exist, use the string template. # If the default template doesn't exist, use the string template.
t = Engine().from_string(CSRF_FAILURE_TEMPLATE) t = Engine().from_string(CSRF_FAILURE_TEMPLATE)
c = Context(c)
else: else:
# Raise if a developer-specified template doesn't exist. # Raise if a developer-specified template doesn't exist.
raise raise

View File

@ -575,6 +575,15 @@ Some undocumented classes in ``django.forms.widgets`` are removed:
The ``Widget.format_output()`` method is removed. Use a custom widget template The ``Widget.format_output()`` method is removed. Use a custom widget template
instead. instead.
``django.Template.render()`` prohibits non-dict context
-------------------------------------------------------
For compatibility with multiple template engines, ``django.Template.render()``
must receive a dictionary of context rather than ``Context`` or
``RequestContext``. If you were passing either of the two classes, pass a
dictionary instead -- doing so is backwards-compatible with older versions of
Django.
Miscellaneous Miscellaneous
------------- -------------

View File

@ -1,6 +1,6 @@
from template_tests.test_response import test_processor_name from template_tests.test_response import test_processor_name
from django.template import EngineHandler from django.template import Context, EngineHandler, RequestContext
from django.template.backends.django import DjangoTemplates from django.template.backends.django import DjangoTemplates
from django.template.library import InvalidTemplateLibrary from django.template.library import InvalidTemplateLibrary
from django.test import RequestFactory, override_settings from django.test import RequestFactory, override_settings
@ -35,6 +35,24 @@ class DjangoTemplatesTests(TemplateStringsTests):
content = template.render({'processors': 'no'}, request) content = template.render({'processors': 'no'}, request)
self.assertEqual(content, 'no') self.assertEqual(content, 'no')
def test_render_requires_dict(self):
"""django.Template.render() requires a dict."""
engine = DjangoTemplates({
'DIRS': [],
'APP_DIRS': False,
'NAME': 'django',
'OPTIONS': {},
})
template = engine.from_string('')
context = Context()
request_context = RequestContext(RequestFactory().get('/'), {})
msg = 'context must be a dict rather than Context.'
with self.assertRaisesMessage(TypeError, msg):
template.render(context)
msg = 'context must be a dict rather than RequestContext.'
with self.assertRaisesMessage(TypeError, msg):
template.render(request_context)
@override_settings(INSTALLED_APPS=['template_backends.apps.good']) @override_settings(INSTALLED_APPS=['template_backends.apps.good'])
def test_templatetag_discovery(self): def test_templatetag_discovery(self):
engine = DjangoTemplates({ engine = DjangoTemplates({