Fixed #208 -- Modernized the syntax of the cycle tag to allow for spaces and variables in cycle values. Thanks to SmileyChris and Chris McAvoy for their work on this.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6153 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a2ce7669d9
commit
09145d2e5f
|
@ -10,7 +10,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{% for result in results %}
|
||||
<tr class="{% cycle row1,row2 %}">{% for item in result %}{{ item }}{% endfor %}</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' %}">{% for item in result %}{{ item }}{% endfor %}</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for field in field_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for year in date_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ year.year }}/">{{ year.year }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ year.year }}/">{{ year.year }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for month in date_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for choice in field.choices %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ choice.url }}">{{ choice.label|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for field in field_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object|iriencode }}/">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{% block content %}
|
||||
|
||||
{% for model in model_list %}
|
||||
<div class="modelgroup {% cycle even,odd %}">
|
||||
<div class="modelgroup {% cycle 'even' 'odd' %}">
|
||||
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
|
||||
<p>
|
||||
{% for object in model.sample_objects %}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<ul class="objectlist">
|
||||
{% for object in model.objects %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<table class="objectinfo">
|
||||
{% for field in object.fields %}
|
||||
<tr class="{% cycle odd,even %}">
|
||||
<tr class="{% cycle 'odd' 'even' %}">
|
||||
<th>{{ field.field.verbose_name|capfirst }}</th>
|
||||
<td>
|
||||
{% if field.urls %}
|
||||
|
@ -29,7 +29,7 @@
|
|||
{% if related_object.object_list %}
|
||||
<ul class="objectlist">
|
||||
{% for object in related_object.object_list %}
|
||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
<li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
|
|
|
@ -30,6 +30,7 @@ class CycleNode(Node):
|
|||
def render(self, context):
|
||||
self.counter += 1
|
||||
value = self.cyclevars[self.counter % self.cyclevars_len]
|
||||
value = resolve_variable(value, context)
|
||||
if self.variable_name:
|
||||
context[self.variable_name] = value
|
||||
return value
|
||||
|
@ -403,7 +404,7 @@ def cycle(parser, token):
|
|||
the loop::
|
||||
|
||||
{% for o in some_list %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
<tr class="{% cycle 'row1' 'row2' %}">
|
||||
...
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -411,16 +412,17 @@ def cycle(parser, token):
|
|||
Outside of a loop, give the values a unique name the first time you call
|
||||
it, then use that name each sucessive time through::
|
||||
|
||||
<tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
|
||||
You can use any number of values, seperated by commas. Make sure not to
|
||||
put spaces between the values -- only commas.
|
||||
You can use any number of values, seperated by spaces. Commas can also
|
||||
be used to separate values; if a comma is used, the cycle values are
|
||||
interpreted as literal strings.
|
||||
"""
|
||||
|
||||
# Note: This returns the exact same node on each {% cycle name %} call; that
|
||||
# is, the node object returned from {% cycle a,b,c as name %} and the one
|
||||
# is, the node object returned from {% cycle a b c as name %} and the one
|
||||
# returned from {% cycle name %} are the exact same object. This shouldn't
|
||||
# cause problems (heh), but if it does, now you know.
|
||||
#
|
||||
|
@ -429,40 +431,34 @@ def cycle(parser, token):
|
|||
# a global variable, which would make cycle names have to be unique across
|
||||
# *all* templates.
|
||||
|
||||
args = token.contents.split()
|
||||
args = token.split_contents()
|
||||
|
||||
if len(args) < 2:
|
||||
raise TemplateSyntaxError("'Cycle' statement requires at least two arguments")
|
||||
raise TemplateSyntaxError("'cycle' tag requires at least two arguments")
|
||||
|
||||
elif len(args) == 2 and "," in args[1]:
|
||||
# {% cycle a,b,c %}
|
||||
cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks
|
||||
return CycleNode(cyclevars)
|
||||
# {% cycle name %}
|
||||
if ',' in args[1]:
|
||||
# Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %}
|
||||
# case.
|
||||
args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
|
||||
|
||||
elif len(args) == 2:
|
||||
if len(args) == 2:
|
||||
# {% cycle foo %} case
|
||||
name = args[1]
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name)
|
||||
if name not in parser._namedCycleNodes:
|
||||
if not name in parser._namedCycleNodes:
|
||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||
return parser._namedCycleNodes[name]
|
||||
|
||||
elif len(args) == 4:
|
||||
# {% cycle a,b,c as name %}
|
||||
if args[2] != 'as':
|
||||
raise TemplateSyntaxError("Second 'cycle' argument must be 'as'")
|
||||
cyclevars = [v for v in args[1].split(",") if v] # split and kill blanks
|
||||
name = args[3]
|
||||
node = CycleNode(cyclevars, name)
|
||||
|
||||
if len(args) > 4 and args[-2] == 'as':
|
||||
name = args[-1]
|
||||
node = CycleNode(args[1:-2], name)
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
parser._namedCycleNodes = {}
|
||||
|
||||
parser._namedCycleNodes[name] = node
|
||||
return node
|
||||
|
||||
else:
|
||||
raise TemplateSyntaxError("Invalid arguments to 'cycle': %s" % args)
|
||||
node = CycleNode(args[1:])
|
||||
return node
|
||||
cycle = register.tag(cycle)
|
||||
|
||||
def debug(parser, token):
|
||||
|
|
|
@ -366,25 +366,36 @@ Ignore everything between ``{% comment %}`` and ``{% endcomment %}``
|
|||
cycle
|
||||
~~~~~
|
||||
|
||||
Cycle among the given strings each time this tag is encountered.
|
||||
**Changed in Django development version**
|
||||
Cycle among the given strings or variables each time this tag is encountered.
|
||||
|
||||
Within a loop, cycles among the given strings each time through the loop::
|
||||
Within a loop, cycles among the given strings/variables each time through the
|
||||
loop::
|
||||
|
||||
{% for o in some_list %}
|
||||
<tr class="{% cycle row1,row2 %}">
|
||||
<tr class="{% cycle 'row1' 'row2' rowvar %}">
|
||||
...
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
Outside of a loop, give the values a unique name the first time you call it,
|
||||
then use that name each successive time through::
|
||||
|
||||
<tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle 'row1' 'row2' rowvar as rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
|
||||
You can use any number of values, separated by commas. Make sure not to put
|
||||
spaces between the values -- only commas.
|
||||
You can use any number of values, separated by spaces. Values enclosed in
|
||||
single (') or double quotes (") are treated as string literals, while values
|
||||
without quotes are assumed to refer to context variables.
|
||||
|
||||
You can also separate values with commas::
|
||||
|
||||
{% cycle row1,row2,row3 %}
|
||||
|
||||
In this syntax, each value will be interpreted as literal text. The
|
||||
comma-based syntax exists for backwards-compatibility, and should not be
|
||||
used for new projects.
|
||||
|
||||
debug
|
||||
~~~~~
|
||||
|
|
|
@ -306,6 +306,14 @@ class Templates(unittest.TestCase):
|
|||
'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
|
||||
'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
|
||||
'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
|
||||
'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||
# New format:
|
||||
'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
|
||||
'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
|
||||
'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
|
||||
'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
|
||||
'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
|
||||
'cycle13': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
|
||||
|
||||
### EXCEPTIONS ############################################################
|
||||
|
||||
|
|
Loading…
Reference in New Issue