diff --git a/django/contrib/admin/templates/admin/change_list_results.html b/django/contrib/admin/templates/admin/change_list_results.html index 3f755783dc..381dcb5d5d 100644 --- a/django/contrib/admin/templates/admin/change_list_results.html +++ b/django/contrib/admin/templates/admin/change_list_results.html @@ -10,7 +10,7 @@ {% for result in results %} -{% for item in result %}{{ item }}{% endfor %} +{% for item in result %}{{ item }}{% endfor %} {% endfor %} diff --git a/django/contrib/databrowse/templates/databrowse/calendar_day.html b/django/contrib/databrowse/templates/databrowse/calendar_day.html index b0f57e1eae..bbb62cc814 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_day.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_day.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html b/django/contrib/databrowse/templates/databrowse/calendar_homepage.html index daf45dfdeb..85eb8af9eb 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_homepage.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/calendar_main.html b/django/contrib/databrowse/templates/databrowse/calendar_main.html index 18ee5bdc8b..b22a44d321 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_main.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_main.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/calendar_month.html b/django/contrib/databrowse/templates/databrowse/calendar_month.html index 67506f452f..70b7deb75a 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_month.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_month.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/calendar_year.html b/django/contrib/databrowse/templates/databrowse/calendar_year.html index 729c2ddf3b..a6e6f53ba3 100644 --- a/django/contrib/databrowse/templates/databrowse/calendar_year.html +++ b/django/contrib/databrowse/templates/databrowse/calendar_year.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/choice_detail.html b/django/contrib/databrowse/templates/databrowse/choice_detail.html index e6add55021..6cb73e73ec 100644 --- a/django/contrib/databrowse/templates/databrowse/choice_detail.html +++ b/django/contrib/databrowse/templates/databrowse/choice_detail.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/choice_list.html b/django/contrib/databrowse/templates/databrowse/choice_list.html index 07a1319459..95cd88b0bf 100644 --- a/django/contrib/databrowse/templates/databrowse/choice_list.html +++ b/django/contrib/databrowse/templates/databrowse/choice_list.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html index d1c8b877cb..7801f3f631 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html index 8760bd4ad1..3259824061 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html index 9f41213a6f..71b906d3e7 100644 --- a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html +++ b/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html @@ -10,7 +10,7 @@ diff --git a/django/contrib/databrowse/templates/databrowse/homepage.html b/django/contrib/databrowse/templates/databrowse/homepage.html index 104a804253..718e577416 100644 --- a/django/contrib/databrowse/templates/databrowse/homepage.html +++ b/django/contrib/databrowse/templates/databrowse/homepage.html @@ -7,7 +7,7 @@ {% block content %} {% for model in model_list %} -
+

{{ model.verbose_name_plural|capfirst }}

{% for object in model.sample_objects %} diff --git a/django/contrib/databrowse/templates/databrowse/model_detail.html b/django/contrib/databrowse/templates/databrowse/model_detail.html index 2084b18ca7..b66bc093dd 100644 --- a/django/contrib/databrowse/templates/databrowse/model_detail.html +++ b/django/contrib/databrowse/templates/databrowse/model_detail.html @@ -12,7 +12,7 @@

diff --git a/django/contrib/databrowse/templates/databrowse/object_detail.html b/django/contrib/databrowse/templates/databrowse/object_detail.html index e9977743fd..7c1bd3e16d 100644 --- a/django/contrib/databrowse/templates/databrowse/object_detail.html +++ b/django/contrib/databrowse/templates/databrowse/object_detail.html @@ -10,7 +10,7 @@ {% for field in object.fields %} - + + ... {% 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:: - ... + ......... - 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): diff --git a/docs/templates.txt b/docs/templates.txt index 9f2bec1c8b..ff67579b87 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -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 %} - + ... {% 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:: - ... + ......... -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 ~~~~~ diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 0f7ac2f352..11dd092156 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -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 ############################################################
{{ field.field.verbose_name|capfirst }} {% if field.urls %} @@ -29,7 +29,7 @@ {% if related_object.object_list %} {% else %} diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 11cd04653f..e41ca717e7 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -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 %} -