summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2014-11-22 09:22:38 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2014-11-22 17:58:38 +0100
commit733178830072caeca3c054a220808b4c557faec4 (patch)
tree74d0eeee1edc9f2861aea82599ab6bc63cbcd2c2
parentbf1bd0fbc9d4920327ad998ad11facf842492e23 (diff)
Avoided rewrapping Contexts in render_to_response.
This change preserves backwards-compatibility for a very common misuse of render_to_response which even occurred in the official documentation. It fixes that misuse wherever it happened in the code base and docs. Context.__init__ is documented as accepting a dict and nothing else. Since Context is dict-like, Context(Context({})) could work to some extent. However, things get complicated with RequestContext and that gets in the way of refactoring the template engine. This is the real rationale for this change.
-rw-r--r--django/contrib/auth/tests/urls.py12
-rw-r--r--django/template/loader.py7
-rw-r--r--docs/topics/i18n/translation.txt5
-rw-r--r--tests/context_processors/views.py5
-rw-r--r--tests/shortcuts/tests.py9
-rw-r--r--tests/shortcuts/urls.py1
-rw-r--r--tests/shortcuts/views.py9
7 files changed, 36 insertions, 12 deletions
diff --git a/django/contrib/auth/tests/urls.py b/django/contrib/auth/tests/urls.py
index 7e9382fb56..8145f2f69c 100644
--- a/django/contrib/auth/tests/urls.py
+++ b/django/contrib/auth/tests/urls.py
@@ -28,7 +28,7 @@ def remote_user_auth_view(request):
def auth_processor_no_attr_access(request):
render_to_response('context_processors/auth_attrs_no_access.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
# *After* rendering, we check whether the session was accessed
return render_to_response('context_processors/auth_attrs_test_access.html',
{'session_accessed': request.session.accessed})
@@ -36,30 +36,30 @@ def auth_processor_no_attr_access(request):
def auth_processor_attr_access(request):
render_to_response('context_processors/auth_attrs_access.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
return render_to_response('context_processors/auth_attrs_test_access.html',
{'session_accessed': request.session.accessed})
def auth_processor_user(request):
return render_to_response('context_processors/auth_attrs_user.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
def auth_processor_perms(request):
return render_to_response('context_processors/auth_attrs_perms.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
def auth_processor_perm_in_perms(request):
return render_to_response('context_processors/auth_attrs_perm_in_perms.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
def auth_processor_messages(request):
info(request, "Message 1")
return render_to_response('context_processors/auth_attrs_messages.html',
- RequestContext(request, {}, processors=[context_processors.auth]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.auth]))
def userpage(request):
diff --git a/django/template/loader.py b/django/template/loader.py
index 093d7d172b..be06d517d2 100644
--- a/django/template/loader.py
+++ b/django/template/loader.py
@@ -65,7 +65,12 @@ def render_to_string(template_name, dictionary=None, context_instance=None,
else:
t = get_template(template_name, dirs)
if not context_instance:
- return t.render(Context(dictionary))
+ # Django < 1.8 accepted a Context in `dictionary` even though that's
+ # unintended. Preserve this ability but don't rewrap `dictionary`.
+ if isinstance(dictionary, Context):
+ return t.render(dictionary)
+ else:
+ return t.render(Context(dictionary))
if not dictionary:
return t.render(context_instance)
# Add the dictionary to the context stack, ensuring it gets removed again
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt
index 8ef9b89c6b..daf66d332b 100644
--- a/docs/topics/i18n/translation.txt
+++ b/docs/topics/i18n/translation.txt
@@ -860,9 +860,8 @@ If you do this in your view:
.. code-block:: python
- return render_to_response('mytemplate.html', {
- 'available_languages': ['en', 'es', 'fr'],
- }, RequestContext(request))
+ context = {'available_languages': ['en', 'es', 'fr']}
+ return render(request, 'mytemplate.html', context)
you can iterate over those languages in the template::
diff --git a/tests/context_processors/views.py b/tests/context_processors/views.py
index 7a00edab0a..077d722750 100644
--- a/tests/context_processors/views.py
+++ b/tests/context_processors/views.py
@@ -8,12 +8,13 @@ from .models import DebugObject
def request_processor(request):
return render_to_response(
'context_processors/request_attrs.html',
- RequestContext(request, {}, processors=[context_processors.request]))
+ context_instance=RequestContext(request, {}, processors=[context_processors.request]))
def debug_processor(request):
+
return render_to_response(
'context_processors/debug.html',
- RequestContext(request, {
+ context_instance=RequestContext(request, {
'debug_objects': DebugObject.objects,
}, processors=[context_processors.debug]))
diff --git a/tests/shortcuts/tests.py b/tests/shortcuts/tests.py
index 4835b40797..24a73d4ffd 100644
--- a/tests/shortcuts/tests.py
+++ b/tests/shortcuts/tests.py
@@ -32,6 +32,15 @@ class ShortcutTests(TestCase):
self.assertEqual(response.content, b'spam eggs\n')
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8')
+ def test_render_to_response_with_context_instance_misuse(self):
+ """
+ For backwards-compatibility, ensure that it's possible to pass a
+ RequestContext instance in the dictionary argument instead of the
+ context_instance argument.
+ """
+ response = self.client.get('/render_to_response/context_instance_misuse/')
+ self.assertContains(response, 'context processor output')
+
def test_render(self):
response = self.client.get('/render/')
self.assertEqual(response.status_code, 200)
diff --git a/tests/shortcuts/urls.py b/tests/shortcuts/urls.py
index cd18c8a01b..f02e74a745 100644
--- a/tests/shortcuts/urls.py
+++ b/tests/shortcuts/urls.py
@@ -7,6 +7,7 @@ urlpatterns = [
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/dirs/$', views.render_to_response_view_with_dirs),
+ 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/base_context/$', views.render_view_with_base_context),
url(r'^render/content_type/$', views.render_view_with_content_type),
diff --git a/tests/shortcuts/views.py b/tests/shortcuts/views.py
index afae78d4d8..c75d324a34 100644
--- a/tests/shortcuts/views.py
+++ b/tests/shortcuts/views.py
@@ -33,6 +33,15 @@ def render_to_response_view_with_dirs(request):
return render_to_response('render_dirs_test.html', dirs=dirs)
+def context_processor(request):
+ return {'bar': 'context processor output'}
+
+
+def render_to_response_with_context_instance_misuse(request):
+ context_instance = RequestContext(request, {}, processors=[context_processor])
+ # Incorrect -- context_instance should be passed as a keyword argument.
+ return render_to_response('shortcuts/render_test.html', context_instance)
+
def render_view(request):
return render(request, 'shortcuts/render_test.html', {
'foo': 'FOO',