- Added `previtem` and `nextitem` to loop contexts, providing access to the
previous/next item in the loop. If such an item does not exist, the value is
undefined.
+- Added `changed(*values)` to loop contexts, providing an easy way of checking
+ whether a value has changed since the last iteration (or rather since the
+ last call of the method)
Version 2.9.6
-------------
| `loop.nextitem` | The item from the following iteration of the loop.|
| | Undefined during the last iteration. |
+-----------------------+---------------------------------------------------+
+| `loop.changed(*val)` | True if previously called with a different value |
+| | (or not called at all). |
++-----------------------+---------------------------------------------------+
Within a for-loop, it's possible to cycle among a list of strings/variables
each time through the loop by using the special `loop.cycle` helper::
{% endif %}
{% endfor %}
+If you only care whether the value changed at all, using `changed` is even
+easier::
+
+ {% for entry in entries %}
+ {% if loop.changed(entry.category) %}
+ <h2>{{ entry.category }}</h2>
+ {% endif %}
+ <p>{{ entry.message }}</p>
+ {% endfor %}
+
.. _if:
If
self._recurse = recurse
self.index0 = -1
self.depth0 = depth0
+ self._last_checked_value = missing
def cycle(self, *args):
"""Cycles among the arguments with the current loop index."""
raise TypeError('no items for cycling given')
return args[self.index0 % len(args)]
+ def changed(self, *value):
+ """Checks whether the value has changed since the last call."""
+ if self._last_checked_value != value:
+ self._last_checked_value = value
+ return True
+ return False
+
first = property(lambda x: x.index0 == 0)
last = property(lambda x: x._after is _last_iteration)
index = property(lambda x: x.index0 + 1)
output = tmpl.render(seq=list(range(4)))
assert output == 'x-0-1|0-1-2|1-2-3|2-3-x|'
+ def test_changed(self, test_env_async):
+ tmpl = test_env_async.from_string('''{% for item in seq -%}
+ {{ loop.changed(item) }},
+ {%- endfor %}''')
+ output = tmpl.render(seq=[None, None, 1, 2, 2, 3, 4, 4, 4])
+ assert output == 'True,False,True,True,False,True,True,False,False,'
+
def test_scope(self, test_env_async):
tmpl = test_env_async.from_string('{% for item in seq %}{% endfor %}{{ item }}')
output = tmpl.render(seq=list(range(10)))
output = tmpl.render(seq=list(range(4)))
assert output == 'x-0-1|0-1-2|1-2-3|2-3-x|'
+ def test_changed(self, env):
+ tmpl = env.from_string('''{% for item in seq -%}
+ {{ loop.changed(item) }},
+ {%- endfor %}''')
+ output = tmpl.render(seq=[None, None, 1, 2, 2, 3, 4, 4, 4])
+ assert output == 'True,False,True,True,False,True,True,False,False,'
+
def test_scope(self, env):
tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
output = tmpl.render(seq=list(range(10)))