Fixed #13567 -- Added a 'silent' argument to the cycle tag, so that you can declare a cycle without producing a value in the template. Thanks to anentropic for the suggestion and initial patch, and Łukasz Rekucki for the final patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14439 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
bb062c376f
commit
a89e02637b
|
@ -53,13 +53,17 @@ class CsrfTokenNode(Node):
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
class CycleNode(Node):
|
class CycleNode(Node):
|
||||||
def __init__(self, cyclevars, variable_name=None):
|
def __init__(self, cyclevars, variable_name=None, silent=False):
|
||||||
self.cyclevars = cyclevars
|
self.cyclevars = cyclevars
|
||||||
self.variable_name = variable_name
|
self.variable_name = variable_name
|
||||||
|
self.silent = silent
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
if self not in context.render_context:
|
if self not in context.render_context:
|
||||||
|
# First time the node is rendered in template
|
||||||
context.render_context[self] = itertools_cycle(self.cyclevars)
|
context.render_context[self] = itertools_cycle(self.cyclevars)
|
||||||
|
if self.silent:
|
||||||
|
return ''
|
||||||
cycle_iter = context.render_context[self]
|
cycle_iter = context.render_context[self]
|
||||||
value = cycle_iter.next().resolve(context)
|
value = cycle_iter.next().resolve(context)
|
||||||
if self.variable_name:
|
if self.variable_name:
|
||||||
|
@ -482,6 +486,17 @@ def cycle(parser, token):
|
||||||
You can use any number of values, separated by spaces. Commas can also
|
You can use any number of values, separated by spaces. Commas can also
|
||||||
be used to separate values; if a comma is used, the cycle values are
|
be used to separate values; if a comma is used, the cycle values are
|
||||||
interpreted as literal strings.
|
interpreted as literal strings.
|
||||||
|
|
||||||
|
The optional flag "silent" can be used to prevent the cycle declaration
|
||||||
|
from returning any value::
|
||||||
|
|
||||||
|
{% cycle 'row1' 'row2' as rowcolors silent %}{# no value here #}
|
||||||
|
{% for o in some_list %}
|
||||||
|
<tr class="{% cycle rowcolors %}">{# first value will be "row1" #}
|
||||||
|
...
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Note: This returns the exact same node on each {% cycle name %} call;
|
# Note: This returns the exact same node on each {% cycle name %} call;
|
||||||
|
@ -513,10 +528,24 @@ def cycle(parser, token):
|
||||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||||
return parser._namedCycleNodes[name]
|
return parser._namedCycleNodes[name]
|
||||||
|
|
||||||
if len(args) > 4 and args[-2] == 'as':
|
as_form = False
|
||||||
|
|
||||||
|
if len(args) > 4:
|
||||||
|
# {% cycle ... as foo [silent] %} case.
|
||||||
|
if args[-3] == "as":
|
||||||
|
if args[-1] != "silent":
|
||||||
|
raise TemplateSyntaxError("Only 'silent' flag is allowed after cycle's name, not '%s'." % args[-1])
|
||||||
|
as_form = True
|
||||||
|
silent = True
|
||||||
|
args = args[:-1]
|
||||||
|
elif args[-2] == "as":
|
||||||
|
as_form = True
|
||||||
|
silent = False
|
||||||
|
|
||||||
|
if as_form:
|
||||||
name = args[-1]
|
name = args[-1]
|
||||||
values = [parser.compile_filter(arg) for arg in args[1:-2]]
|
values = [parser.compile_filter(arg) for arg in args[1:-2]]
|
||||||
node = CycleNode(values, name)
|
node = CycleNode(values, name, silent=silent)
|
||||||
if not hasattr(parser, '_namedCycleNodes'):
|
if not hasattr(parser, '_namedCycleNodes'):
|
||||||
parser._namedCycleNodes = {}
|
parser._namedCycleNodes = {}
|
||||||
parser._namedCycleNodes[name] = node
|
parser._namedCycleNodes[name] = node
|
||||||
|
|
|
@ -140,6 +140,26 @@ In this syntax, each value gets interpreted as a literal string, and there's no
|
||||||
way to specify variable values. Or literal commas. Or spaces. Did we mention
|
way to specify variable values. Or literal commas. Or spaces. Did we mention
|
||||||
you shouldn't use this syntax in any new projects?
|
you shouldn't use this syntax in any new projects?
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
By default, when you use the ``as`` keyword with the cycle tag, the
|
||||||
|
usage of ``{% cycle %}`` that declares the cycle will itself output
|
||||||
|
the first value in the cycle. This could be a problem if you want to
|
||||||
|
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 %}
|
||||||
|
<tr class="{% cycle rowcolors %}">{{ obj }}</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
This will output a list of ``<tr>`` 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 ``<tr>`` elements, and the first ``<tr>`` would have a
|
||||||
|
class of ``row2``.
|
||||||
|
|
||||||
.. templatetag:: debug
|
.. templatetag:: debug
|
||||||
|
|
||||||
debug
|
debug
|
||||||
|
|
|
@ -646,6 +646,9 @@ class Templates(unittest.TestCase):
|
||||||
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
|
'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,'),
|
'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'),
|
'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"),
|
||||||
|
'cycle18': ("{% cycle 'a' 'b' 'c' as foo invalid_flag %}", {}, template.TemplateSyntaxError),
|
||||||
|
'cycle19': ("{% cycle 'a' 'b' as silent %}{% cycle silent %}", {}, "ab"),
|
||||||
|
|
||||||
### EXCEPTIONS ############################################################
|
### EXCEPTIONS ############################################################
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue