Fixed #26830 -- Prevented the 'with' templatetag from resetting the cycle variable to its initial state.
This commit is contained in:
parent
31e053edfa
commit
3ae3a1f9fa
|
@ -67,6 +67,18 @@ class BaseContext(object):
|
|||
"Set a variable in the current context"
|
||||
self.dicts[-1][key] = value
|
||||
|
||||
def set_upward(self, key, value):
|
||||
"""
|
||||
Set a variable in one of the higher contexts if it exists there,
|
||||
otherwise in the current context.
|
||||
"""
|
||||
context = self.dicts[-1]
|
||||
for d in reversed(self.dicts):
|
||||
if key in d.keys():
|
||||
context = d
|
||||
break
|
||||
context[key] = value
|
||||
|
||||
def __getitem__(self, key):
|
||||
"Get a variable's value, starting at the current context and going upward"
|
||||
for d in reversed(self.dicts):
|
||||
|
|
|
@ -82,7 +82,7 @@ class CycleNode(Node):
|
|||
cycle_iter = context.render_context[self]
|
||||
value = next(cycle_iter).resolve(context)
|
||||
if self.variable_name:
|
||||
context[self.variable_name] = value
|
||||
context.set_upward(self.variable_name, value)
|
||||
if self.silent:
|
||||
return ''
|
||||
return render_value_in_context(value, context)
|
||||
|
|
|
@ -145,3 +145,25 @@ class CycleTagTests(SimpleTestCase):
|
|||
"""
|
||||
output = self.engine.render_to_string('cycle29', {'values': [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 9, 9]})
|
||||
self.assertEqual(output, 'bcabcabcccaa')
|
||||
|
||||
@setup({
|
||||
'cycle30': "{% cycle 'a' 'b' 'c' as cycler silent %}"
|
||||
"{% for x in values %}"
|
||||
"{% with doesnothing=irrelevant %}"
|
||||
"{% ifchanged x %}"
|
||||
"{% cycle cycler %}{{ cycler }}"
|
||||
"{% else %}"
|
||||
"{{ cycler }}"
|
||||
"{% endifchanged %}"
|
||||
"{% endwith %}"
|
||||
"{% endfor %}"})
|
||||
def test_cycle30(self):
|
||||
"""
|
||||
A {% with %} tag shouldn't reset the {% cycle %} variable.
|
||||
"""
|
||||
output = self.engine.render_to_string(
|
||||
'cycle30', {
|
||||
'irrelevant': 1,
|
||||
'values': [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 9, 9]
|
||||
})
|
||||
self.assertEqual(output, 'bcabcabcccaa')
|
||||
|
|
|
@ -204,6 +204,37 @@ class ContextTests(SimpleTestCase):
|
|||
self.assertEqual(str(warns[2].message), msg2)
|
||||
self.assertEqual(str(warns[3].message), msg2)
|
||||
|
||||
def test_set_upward(self):
|
||||
c = Context({'a': 1})
|
||||
c.set_upward('a', 2)
|
||||
self.assertEqual(c.get('a'), 2)
|
||||
|
||||
def test_set_upward_empty_context(self):
|
||||
empty_context = Context()
|
||||
empty_context.set_upward('a', 1)
|
||||
self.assertEqual(empty_context.get('a'), 1)
|
||||
|
||||
def test_set_upward_with_push(self):
|
||||
"""
|
||||
The highest context which has the given key is used.
|
||||
"""
|
||||
c = Context({'a': 1})
|
||||
c.push({'a': 2})
|
||||
c.set_upward('a', 3)
|
||||
self.assertEqual(c.get('a'), 3)
|
||||
c.pop()
|
||||
self.assertEqual(c.get('a'), 1)
|
||||
|
||||
def test_set_upward_with_push_no_match(self):
|
||||
"""
|
||||
The highest context is used if the given key isn't found.
|
||||
"""
|
||||
c = Context({'b': 1})
|
||||
c.push({'b': 2})
|
||||
c.set_upward('a', 2)
|
||||
self.assertEqual(len(c.dicts), 3)
|
||||
self.assertEqual(c.dicts[-1]['a'], 2)
|
||||
|
||||
|
||||
class RequestContextTests(SimpleTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue