summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek WywiaƂ <onjinx@gmail.com>2014-02-16 14:50:27 +0100
committerBaptiste Mispelon <bmispelon@gmail.com>2014-02-16 15:18:45 +0100
commit8274fa60f88607eb0e81908f049c391455956dd8 (patch)
tree7405dd7591d3b710e19d758c153231e2063789a0
parent57ba5bf97b13acdaccd6e091e6f23b619a6faedb (diff)
Made the new template.Context.flatten() method a public API.
That method was introduced in 9db4271bd11ac23a5a5652bbcdf8fb6d4b997651. Refs #21765.
-rw-r--r--django/template/context.py17
-rw-r--r--docs/ref/templates/api.txt37
-rw-r--r--docs/releases/1.7.txt8
-rw-r--r--tests/template_tests/test_context.py11
4 files changed, 66 insertions, 7 deletions
diff --git a/django/template/context.py b/django/template/context.py
index b2f00abd31..76af916cb7 100644
--- a/django/template/context.py
+++ b/django/template/context.py
@@ -97,6 +97,15 @@ class BaseContext(object):
new_context._reset_dicts(values)
return new_context
+ def flatten(self):
+ """
+ Returns self.dicts as one dictionary
+ """
+ flat = {}
+ for d in self.dicts:
+ flat.update(d)
+ return flat
+
def __eq__(self, other):
"""
Compares two contexts by comparing theirs 'dicts' attributes.
@@ -104,13 +113,7 @@ class BaseContext(object):
if isinstance(other, BaseContext):
# because dictionaries can be put in different order
# we have to flatten them like in templates
- def flatten(dicts):
- flat = {}
- for d in dicts:
- flat.update(d)
- return flat
-
- return flatten(self.dicts) == flatten(other.dicts)
+ return self.flatten() == other.flatten()
# if it's not comparable return false
return False
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
index 7627c02b6e..5701b1a9d1 100644
--- a/docs/ref/templates/api.txt
+++ b/docs/ref/templates/api.txt
@@ -368,6 +368,43 @@ the stack instead of an empty one.
Using a ``Context`` as a stack comes in handy in some custom template tags, as
you'll see below.
+.. method:: Context.flatten()
+
+.. versionadded:: 1.7
+
+Using ``flatten()`` method you can get whole ``Context`` stack as one dictionary
+including builtin variables.
+
+ >>> c = Context()
+ >>> c['foo'] = 'first level'
+ >>> c.update({'bar': 'second level'})
+ {'bar': 'second level'}
+ >>> c.flatten()
+ {'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}
+
+A ``flatten()`` method is also internally used to make ``Context`` objects comparable.
+
+ >>> c1 = Context()
+ >>> c1['foo'] = 'first level'
+ >>> c1['bar'] = 'second level'
+ >>> c2 = Context()
+ >>> c2.update({'bar': 'second level', 'foo': 'first level'})
+ {'foo': 'first level', 'bar': 'second level'}
+ >>> c1 == c2
+ True
+
+Result from ``flatten()`` can be useful in unit tests to compare ``Context``
+against ``dict``::
+
+ class ContextTest(unittest.TestCase):
+ def test_against_dictionary(self):
+ c1 = Context()
+ c1['update'] = 'value'
+ self.assertEqual(c1.flatten(), {
+ 'True': True, 'None': None, 'False': False,
+ 'update': 'value'})
+
+
.. _subclassing-context-requestcontext:
Subclassing Context: RequestContext
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index cd9a9dd225..8e241caf44 100644
--- a/docs/releases/1.7.txt
+++ b/docs/releases/1.7.txt
@@ -636,6 +636,14 @@ Templates
parameters that are passed to the ``dict`` constructor used to build the new
context level.
+* The new :meth:`Context.flatten() <django.template.Context.flatten>` method
+ returns a ``Context``'s stack as one flat dictionary.
+
+* ``Context`` objects can now be compared for equality (internally, this
+ uses :meth:`Context.flatten() <django.template.Context.flatten>` so the
+ internal structure of each ``Context``'s stack doesn't matter as long as their
+ flattened version is identical).
+
* The :ttag:`widthratio` template tag now accepts an "as" parameter to capture
the result in a variable.
diff --git a/tests/template_tests/test_context.py b/tests/template_tests/test_context.py
index 64d0df8d10..dac74b36e3 100644
--- a/tests/template_tests/test_context.py
+++ b/tests/template_tests/test_context.py
@@ -50,6 +50,17 @@ class ContextTests(TestCase):
test_context['fruit']
self.assertIsNone(test_context.get('fruit'))
+ def test_flatten_context(self):
+ a = Context()
+ a.update({'a': 2})
+ a.update({'b': 4})
+ a.update({'c': 8})
+
+ self.assertEqual(a.flatten(), {
+ 'False': False, 'None': None, 'True': True,
+ 'a': 2, 'b': 4, 'c': 8
+ })
+
def test_context_comparable(self):
test_data = {'x': 'y', 'v': 'z', 'd': {'o': object, 'a': 'b'}}