diff --git a/django/template/context.py b/django/template/context.py index 2434b31a68..778a83d7a3 100644 --- a/django/template/context.py +++ b/django/template/context.py @@ -171,8 +171,7 @@ class Context(BaseContext): "Pushes other_dict to the stack of dictionaries in the Context" if not hasattr(other_dict, '__getitem__'): raise TypeError('other_dict must be a mapping (dictionary-like) object.') - self.dicts.append(other_dict) - return other_dict + return ContextDict(self, other_dict) class RenderContext(BaseContext): diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt index 077330f6ce..5e56eff1d4 100644 --- a/docs/ref/templates/api.txt +++ b/docs/ref/templates/api.txt @@ -497,6 +497,21 @@ the stack instead of an empty one. >>> c['foo'] 'first level' +Like ``push()``, you can use ``update()`` as a context manager to ensure a +matching ``pop()`` is called. + + >>> c = Context() + >>> c['foo'] = 'first level' + >>> with c.update({'foo': 'second level'}): + ... c['foo'] + 'second level' + >>> c['foo'] + 'first level' + +.. versionadded:: 1.9 + + The ability to use ``update()`` as a context manager was added. + Using a ``Context`` as a stack comes in handy in :ref:`some custom template tags `. diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 47c2bc98bc..25da6978ba 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -211,6 +211,9 @@ Templates * The :ttag:`firstof` template tag supports storing the output in a variable using 'as'. +* :meth:`Context.update() ` can now be used as + a context manager. + Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/template_tests/test_context.py b/tests/template_tests/test_context.py index 9c23a38af2..f7959e6415 100644 --- a/tests/template_tests/test_context.py +++ b/tests/template_tests/test_context.py @@ -21,6 +21,8 @@ class ContextTests(SimpleTestCase): self.assertEqual(c["a"], 1) self.assertEqual(c.get("foo", 42), 42) + def test_push_context_manager(self): + c = Context({"a": 1}) with c.push(): c['a'] = 2 self.assertEqual(c['a'], 2) @@ -30,6 +32,17 @@ class ContextTests(SimpleTestCase): self.assertEqual(c['a'], 3) self.assertEqual(c['a'], 1) + def test_update_context_manager(self): + c = Context({"a": 1}) + with c.update({}): + c['a'] = 2 + self.assertEqual(c['a'], 2) + self.assertEqual(c['a'], 1) + + with c.update({'a': 3}): + self.assertEqual(c['a'], 3) + self.assertEqual(c['a'], 1) + def test_setdefault(self): c = Context()