Commits

Anonymous committed 34cf6f0

[1.2.X] Ensure render_to_string leaves the context instance stack in the state it was originally passed in.

Backport of r15591 from trunk.

Comments (0)

Files changed (3)

django/template/loader.py

         t = select_template(template_name)
     else:
         t = get_template(template_name)
-    if context_instance:
-        context_instance.update(dictionary)
-    else:
-        context_instance = Context(dictionary)
-    return t.render(context_instance)
+    if not context_instance:
+        return t.render(Context(dictionary))
+    # Add the dictionary to the context stack, ensuring it gets removed again
+    # to keep the context_instance in the same state it started in.
+    context_instance.update(dictionary)
+    try:
+        return t.render(context_instance)
+    finally:
+        context_instance.pop()
 
 def select_template(template_name_list):
     "Given a list of template names, returns the first that can be loaded."

tests/regressiontests/templates/loaders.py

         # The two templates should not have the same content
         self.assertNotEqual(t1.render(Context({})), t2.render(Context({})))
 
+class RenderToStringTest(unittest.TestCase):
+
+    def setUp(self):
+        self._old_TEMPLATE_DIRS = settings.TEMPLATE_DIRS
+        settings.TEMPLATE_DIRS = (
+            os.path.join(os.path.dirname(__file__), 'templates'),
+        )
+
+    def tearDown(self):
+        settings.TEMPLATE_DIRS = self._old_TEMPLATE_DIRS
+
+    def test_basic(self):
+        self.assertEqual(loader.render_to_string('test_context.html'), 'obj:')
+
+    def test_basic_context(self):
+        self.assertEqual(loader.render_to_string('test_context.html',
+                                                 {'obj': 'test'}), 'obj:test')
+
+    def test_existing_context_kept_clean(self):
+        context = Context({'obj': 'before'})
+        output = loader.render_to_string('test_context.html', {'obj': 'after'},
+                                         context_instance=context)
+        self.assertEqual(output, 'obj:after')
+        self.assertEqual(context['obj'], 'before')
+
 if __name__ == "__main__":
     unittest.main()

tests/regressiontests/templates/templates/test_context.html

+obj:{{ obj }}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.