diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 26ff986b6d..a3b08a9120 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -654,6 +654,10 @@ def cycle(parser, token): raise TemplateSyntaxError("'cycle' tag requires at least two arguments") if ',' in args[1]: + warnings.warn( + "The old {% cycle %} syntax with comma-separated arguments is deprecated.", + RemovedInDjango20Warning, + ) # Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %} # case. args[1:2] = ['"%s"' % arg for arg in args[1].split(",")] diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index a597baf439..cb5d989450 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -187,6 +187,9 @@ details on these changes. from ``allow_migrate(self, db, model)`` to ``allow_migrate(self, db, app_label, model_name=None, **hints)``. +* Support for the syntax of ``{% cycle %}`` that uses comma-separated arguments + will be removed. + .. _deprecation-removed-in-1.9: 1.9 diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 4c7d1d6031..aef4443c6a 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -185,17 +185,17 @@ call to ``{% cycle %}`` doesn't specify ``silent``:: {% cycle 'row1' 'row2' as rowcolors silent %} {% cycle rowcolors %} -For backward compatibility, the ``{% cycle %}`` tag supports the much inferior -old syntax from previous Django versions. You shouldn't use this in any new -projects, but for the sake of the people who are still using it, here's what it -looks like:: +.. deprecated:: 1.9 - {% cycle row1,row2,row3 %} + The ``{% cycle %}`` tag supports the much inferior old syntax from previous + Django versions. You shouldn't use this in any new projects, but for the + sake of the people who are still using it, here's what it looks like:: -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 -you shouldn't use this syntax in any new projects? + {% cycle row1,row2,row3 %} + In this syntax, each value gets interpreted as a literal string, and there's + no way to specify variable values, literal commas, or spaces. Support for + this syntax will be removed in Django 2.0. .. templatetag:: debug diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 4cfdaaa1eb..b75216fbc6 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -277,6 +277,19 @@ template tags that store results in a template variable. The ability, making the ``assignment_tag`` obsolete. Tags that use ``assignment_tag`` should be updated to use ``simple_tag``. +``{% cycle %}`` syntax with comma-separated arguments +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :ttag:`cycle` tag supports an inferior old syntax from previous Django +versions: + +.. code-block:: html+django + + {% cycle row1,row2,row3 %} + +Its parsing caused bugs with the current syntax, so support for the old syntax +will be removed in Django 2.0 following an accelerated deprecation. + Miscellaneous ~~~~~~~~~~~~~ diff --git a/tests/template_tests/syntax_tests/test_cycle.py b/tests/template_tests/syntax_tests/test_cycle.py index 88a7187b1a..e2edf94c8d 100644 --- a/tests/template_tests/syntax_tests/test_cycle.py +++ b/tests/template_tests/syntax_tests/test_cycle.py @@ -12,16 +12,19 @@ class CycleTagTests(SimpleTestCase): with self.assertRaises(TemplateSyntaxError): self.engine.get_template('cycle01') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle02': '{% cycle a,b,c as abc %}{% cycle abc %}'}) def test_cycle02(self): output = self.engine.render_to_string('cycle02') self.assertEqual(output, 'ab') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle03': '{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}'}) def test_cycle03(self): output = self.engine.render_to_string('cycle03') self.assertEqual(output, 'abc') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle04': '{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}'}) def test_cycle04(self): output = self.engine.render_to_string('cycle04') @@ -37,16 +40,19 @@ class CycleTagTests(SimpleTestCase): with self.assertRaises(TemplateSyntaxError): self.engine.get_template('cycle06') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle07': '{% cycle a,b,c as foo %}{% cycle bar %}'}) def test_cycle07(self): with self.assertRaises(TemplateSyntaxError): self.engine.get_template('cycle07') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle08': '{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}'}) def test_cycle08(self): output = self.engine.render_to_string('cycle08') self.assertEqual(output, 'abbbcc') + @ignore_warnings(category=RemovedInDjango20Warning) @setup({'cycle09': '{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}'}) def test_cycle09(self): output = self.engine.render_to_string('cycle09', {'test': list(range(5))}) diff --git a/tests/template_tests/syntax_tests/test_if_changed.py b/tests/template_tests/syntax_tests/test_if_changed.py index 33e66880dd..b06c0bbdd9 100644 --- a/tests/template_tests/syntax_tests/test_if_changed.py +++ b/tests/template_tests/syntax_tests/test_if_changed.py @@ -124,14 +124,14 @@ class IfChangedTagTests(SimpleTestCase): self.assertEqual(output, '1-first,1-other,2-first,2-other,2-other,3-first,') @setup({'ifchanged-else02': '{% for id in ids %}{{ id }}-' - '{% ifchanged id %}{% cycle red,blue %}{% else %}grey{% endifchanged %}' + '{% ifchanged id %}{% cycle "red" "blue" %}{% else %}grey{% endifchanged %}' ',{% endfor %}'}) def test_ifchanged_else02(self): output = self.engine.render_to_string('ifchanged-else02', {'ids': [1, 1, 2, 2, 2, 3]}) self.assertEqual(output, '1-red,1-grey,2-blue,2-grey,2-grey,3-red,') @setup({'ifchanged-else03': '{% for id in ids %}{{ id }}' - '{% ifchanged id %}-{% cycle red,blue %}{% else %}{% endifchanged %}' + '{% ifchanged id %}-{% cycle "red" "blue" %}{% else %}{% endifchanged %}' ',{% endfor %}'}) def test_ifchanged_else03(self): output = self.engine.render_to_string('ifchanged-else03', {'ids': [1, 1, 2, 2, 2, 3]})