Browse Source

Fixed #25236 -- Deprecated {% ifequal %} and {% ifnotequal %} template tags.

The {% if %} tag provides all features of these tags.

Since Django 1.2 (May 17, 2010), the docs have hinted that
{% ifequal %} and {% ifnotequal %} will be deprecated in a future
Django version. Time to make it official.
Jon Dufresne 4 years ago
parent
commit
72a170b4c3

+ 12 - 0
django/template/defaulttags.py

@@ -8,6 +8,7 @@ from itertools import cycle as itertools_cycle, groupby
 
 from django.conf import settings
 from django.utils import timezone
+from django.utils.deprecation import RemovedInDjango40Warning
 from django.utils.html import conditional_escape, format_html
 from django.utils.lorem_ipsum import paragraphs, words
 from django.utils.safestring import mark_safe
@@ -261,6 +262,7 @@ class IfChangedNode(Node):
 
 
 class IfEqualNode(Node):
+    # RemovedInDjango40Warning.
     child_nodelists = ('nodelist_true', 'nodelist_false')
 
     def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
@@ -820,6 +822,7 @@ def do_for(parser, token):
 
 
 def do_ifequal(parser, token, negate):
+    # RemovedInDjango40Warning.
     bits = list(token.split_contents())
     if len(bits) != 3:
         raise TemplateSyntaxError("%r takes two arguments" % bits[0])
@@ -853,6 +856,10 @@ def ifequal(parser, token):
             ...
         {% endifnotequal %}
     """
+    warnings.warn(
+        'The {% ifequal %} template tag is deprecated in favor of {% if %}.',
+        RemovedInDjango40Warning,
+    )
     return do_ifequal(parser, token, False)
 
 
@@ -862,6 +869,11 @@ def ifnotequal(parser, token):
     Output the contents of the block if the two arguments are not equal.
     See ifequal.
     """
+    warnings.warn(
+        'The {% ifnotequal %} template tag is deprecated in favor of '
+        '{% if %}.',
+        RemovedInDjango40Warning,
+    )
     return do_ifequal(parser, token, True)
 
 

+ 2 - 0
docs/internals/deprecation.txt

@@ -90,6 +90,8 @@ details on these changes.
   ``django.contrib.postgres.fields.jsonb.KeyTransform``, and
   ``django.contrib.postgres.fields.jsonb.KeyTextTransform`` will be removed.
 
+* The ``{% ifequal %}`` and ``{% ifnotequal %}`` template tags will be removed.
+
 See the :ref:`Django 3.1 release notes <deprecated-features-3.1>` for more
 details on these changes.
 

+ 2 - 1
docs/ref/templates/builtins.txt

@@ -611,10 +611,11 @@ you should use::
 ``ifequal`` and ``ifnotequal``
 ------------------------------
 
+.. deprecated:: 3.1
+
 ``{% ifequal a b %} ... {% endifequal %}`` is an obsolete way to write
 ``{% if a == b %} ... {% endif %}``. Likewise, ``{% ifnotequal a b %} ...
 {% endifnotequal %}`` is superseded by ``{% if a != b %} ... {% endif %}``.
-The ``ifequal`` and ``ifnotequal`` tags will be deprecated in a future release.
 
 .. templatetag:: ifchanged
 

+ 7 - 0
docs/releases/3.1.txt

@@ -812,6 +812,13 @@ Miscellaneous
 * ``django.conf.urls.url()`` alias of :func:`django.urls.re_path` is
   deprecated.
 
+* The ``{% ifequal %}`` and ``{% ifnotequal %}`` template tags are deprecated
+  in favor of :ttag:`{% if %}<if>`. ``{% if %}`` covers all use cases, but if
+  you need to continue using these tags, they can be extracted from Django to a
+  module and included as a built-in tag in the :class:`'builtins'
+  <django.template.backends.django.DjangoTemplates>` option in
+  :setting:`OPTIONS <TEMPLATES-OPTIONS>`.
+
 .. _removed-features-3.1:
 
 Features removed in 3.1

+ 3 - 1
tests/template_tests/syntax_tests/test_autoescape.py

@@ -1,5 +1,6 @@
 from django.template import TemplateSyntaxError
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase, ignore_warnings
+from django.utils.deprecation import RemovedInDjango40Warning
 from django.utils.safestring import mark_safe
 
 from ..utils import SafeClass, UnsafeClass, setup
@@ -81,6 +82,7 @@ class AutoescapeTagTests(SimpleTestCase):
         with self.assertRaises(TemplateSyntaxError):
             self.engine.render_to_string('autoescape-filtertag01', {'first': '<a>'})
 
+    @ignore_warnings(category=RemovedInDjango40Warning)
     @setup({'autoescape-ifequal01': '{% ifequal var "this & that" %}yes{% endifequal %}'})
     def test_autoescape_ifequal01(self):
         """

+ 29 - 2
tests/template_tests/syntax_tests/test_if_equal.py

@@ -1,10 +1,12 @@
 from django.template import TemplateSyntaxError
 from django.template.defaulttags import IfEqualNode
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase, ignore_warnings
+from django.utils.deprecation import RemovedInDjango40Warning
 
 from ..utils import setup
 
 
+@ignore_warnings(category=RemovedInDjango40Warning)
 class IfEqualTagTests(SimpleTestCase):
 
     @setup({'ifequal01': '{% ifequal a b %}yes{% endifequal %}'})
@@ -196,6 +198,7 @@ class IfEqualTagTests(SimpleTestCase):
         self.assertEqual(output, 'x')
 
 
+@ignore_warnings(category=RemovedInDjango40Warning)
 class IfNotEqualTagTests(SimpleTestCase):
 
     @setup({'ifnotequal01': '{% ifnotequal a b %}yes{% endifnotequal %}'})
@@ -224,7 +227,31 @@ class IfNotEqualTagTests(SimpleTestCase):
             self.engine.render_to_string('one_var', {'a': 1})
 
 
-class IfEqualTests(SimpleTestCase):
+class DeprecationTests(SimpleTestCase):
+    @setup(
+        {'ifequal_warning': '{% ifequal a b %}yes{% endifequal %}'},
+        test_once=True,
+    )
+    def test_ifequal_warning(self):
+        msg = (
+            'The {% ifequal %} template tag is deprecated in favor of '
+            '{% if %}.'
+        )
+        with self.assertRaisesMessage(RemovedInDjango40Warning, msg):
+            self.engine.render_to_string('ifequal_warning', {'a': 1, 'b': 2})
+
+    @setup(
+        {'ifnotequal_warning': '{% ifnotequal a b %}yes{% endifnoequal %}'},
+        test_once=True,
+    )
+    def test_ifnotequal_warning(self):
+        msg = (
+            'The {% ifnotequal %} template tag is deprecated in favor of '
+            '{% if %}.'
+        )
+        with self.assertRaisesMessage(RemovedInDjango40Warning, msg):
+            self.engine.render_to_string('ifnotequal_warning', {'a': 1, 'b': 2})
+
     def test_repr(self):
         node = IfEqualNode(var1='a', var2='b', nodelist_true=[], nodelist_false=[], negate=False)
         self.assertEqual(repr(node), '<IfEqualNode>')

+ 4 - 4
tests/template_tests/syntax_tests/test_resetcycle.py

@@ -75,9 +75,9 @@ class ResetCycleTagTests(SimpleTestCase):
     @setup({'resetcycle10': "{% for i in test %}"
                             "{% cycle 'X' 'Y' 'Z' as XYZ %}"
                             "{% cycle 'a' 'b' 'c' as abc %}"
-                            "{% ifequal i 1 %}"
+                            "{% if i == 1 %}"
                             "{% resetcycle abc %}"
-                            "{% endifequal %}"
+                            "{% endif %}"
                             "{% endfor %}"})
     def test_resetcycle10(self):
         output = self.engine.render_to_string('resetcycle10', {'test': list(range(5))})
@@ -86,9 +86,9 @@ class ResetCycleTagTests(SimpleTestCase):
     @setup({'resetcycle11': "{% for i in test %}"
                             "{% cycle 'X' 'Y' 'Z' as XYZ %}"
                             "{% cycle 'a' 'b' 'c' as abc %}"
-                            "{% ifequal i 1 %}"
+                            "{% if i == 1 %}"
                             "{% resetcycle XYZ %}"
-                            "{% endifequal %}"
+                            "{% endif %}"
                             "{% endfor %}"})
     def test_resetcycle11(self):
         output = self.engine.render_to_string('resetcycle11', {'test': list(range(5))})

+ 3 - 1
tests/template_tests/test_nodelist.py

@@ -1,6 +1,7 @@
 from django.template import Context, Engine
 from django.template.base import TextNode, VariableNode
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase, ignore_warnings
+from django.utils.deprecation import RemovedInDjango40Warning
 
 
 class NodelistTest(SimpleTestCase):
@@ -20,6 +21,7 @@ class NodelistTest(SimpleTestCase):
         vars = template.nodelist.get_nodes_by_type(VariableNode)
         self.assertEqual(len(vars), 1)
 
+    @ignore_warnings(category=RemovedInDjango40Warning)
     def test_ifequal(self):
         template = self.engine.from_string('{% ifequal x y %}{{ a }}{% endifequal %}')
         vars = template.nodelist.get_nodes_by_type(VariableNode)