From c260c533e1f1553548fc98f24820805af87f72bf Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 8 Mar 2011 13:43:53 +0000 Subject: [PATCH] Fixed #15570 -- Corrected a flaw in the design of the silent flag on {% cycle %}. Thanks to Brian Neal for the report, and to Andrew and Jannis for the design consult. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15773 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/template/defaulttags.py | 4 +- docs/ref/templates/builtins.txt | 49 +++++++++++++++++++----- tests/regressiontests/templates/tests.py | 6 ++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 0662b5f2e7..ff97d92d75 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -111,12 +111,12 @@ class CycleNode(Node): if self not in context.render_context: # First time the node is rendered in template context.render_context[self] = itertools_cycle(self.cyclevars) - if self.silent: - return '' cycle_iter = context.render_context[self] value = cycle_iter.next().resolve(context) if self.variable_name: context[self.variable_name] = value + if self.silent: + return '' return value class DebugNode(Node): diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 1befa89e6c..1fa495e51a 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -102,11 +102,31 @@ outside of a loop. To do this, just give the ``{% cycle %}`` tag a name, using {% cycle 'row1' 'row2' as rowcolors %} -From then on, you can insert the current value of the cycle wherever you'd like -in your template:: +From then on, you can insert the current value of the cycle wherever +you'd like in your template by referencing the cycle name as a context +variable. If you want to move the cycle onto the next value, you use +the cycle tag again, using the name of the variable. So, the following +template:: - ... - ... + + ... + ... + + + ... + ... + + +would output:: + + + ... + ... + + + ... + ... + You can use any number of values in a ``{% cycle %}`` tag, separated by spaces. Values enclosed in single (``'``) or double quotes (``"``) are treated as @@ -144,16 +164,25 @@ use the value in a nested loop or an included template. If you want to just declare the cycle, but not output the first value, you can add a ``silent`` keyword as the last keyword in the tag. For example:: - {% cycle 'row1' 'row2' as rowcolors silent %} {% for obj in some_list %} - {{ obj }} + {% cycle 'row1' 'row2' as rowcolors silent %} + {% include "subtemplate.html " %} {% endfor %} This will output a list of ```` elements with ``class`` -alternating between ``row1`` and ``row2``. If the ``silent`` keyword -were to be omitted, ``row1`` would be emitted as normal text, outside -the list of ```` elements, and the first ```` would have a -class of ``row2``. +alternating between ``row1`` and ``row2``; the subtemplate will have +access to ``rowcolors`` in it's context that matches the class of the +```` that encloses it. If the ``silent`` keyword were to be +omitted, ``row1`` would be emitted as normal text, outside the +```` element. + +When the silent keyword is used on a cycle definition, the silence +automatically applies to all subsequent uses of the cycle tag. In, +the following template would output *nothing*, even though the second +call to ``{% cycle %}`` doesn't specify silent:: + + {% cycle 'row1' 'row2' as rowcolors silent %} + {% cycle rowcolors %} .. templatetag:: debug diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 49951d8698..46aedb3da6 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -735,11 +735,15 @@ class Templates(unittest.TestCase): 'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'), 'cycle15': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'), 'cycle16': ("{% cycle one|lower two as foo %}{% cycle foo %}", {'one': 'A','two': '2'}, 'a2'), - 'cycle17': ("{% cycle 'a' 'b' 'c' as abc silent %}{% cycle abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, "abca"), + 'cycle17': ("{% cycle 'a' 'b' 'c' as abc silent %}{% cycle abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, ""), 'cycle18': ("{% cycle 'a' 'b' 'c' as foo invalid_flag %}", {}, template.TemplateSyntaxError), 'cycle19': ("{% cycle 'a' 'b' as silent %}{% cycle silent %}", {}, "ab"), 'cycle20': ("{% cycle one two as foo %} & {% cycle foo %}", {'one' : 'A & B', 'two' : 'C & D'}, "A & B & C & D"), 'cycle21': ("{% filter force_escape %}{% cycle one two as foo %} & {% cycle foo %}{% endfilter %}", {'one' : 'A & B', 'two' : 'C & D'}, "A & B & C & D"), + 'cycle22': ("{% for x in values %}{% cycle 'a' 'b' 'c' as abc silent %}{{ x }}{% endfor %}", {'values': [1,2,3,4]}, "1234"), + 'cycle23': ("{% for x in values %}{% cycle 'a' 'b' 'c' as abc silent %}{{ abc }}{{ x }}{% endfor %}", {'values': [1,2,3,4]}, "a1b2c3a4"), + 'included-cycle': ('{{ abc }}', {'abc': 'xxx'}, 'xxx'), + 'cycle24': ("{% for x in values %}{% cycle 'a' 'b' 'c' as abc silent %}{% include 'included-cycle' %}{% endfor %}", {'values': [1,2,3,4]}, "abca"), ### EXCEPTIONS ############################################################