Browse Source

Fixed #33864 -- Deprecated length_is template filter.

Nick Pope 3 years ago
parent
commit
4d4bf55e0e

+ 4 - 4
django/contrib/admin/templates/admin/includes/fieldset.html

@@ -4,11 +4,11 @@
         <div class="description">{{ fieldset.description|safe }}</div>
     {% endif %}
     {% for line in fieldset %}
-        <div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
-            {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
+        <div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
+            {% if line.fields|length == 1 %}{{ line.errors }}{% endif %}
             {% for field in line %}
-                <div{% if not line.fields|length_is:'1' %} class="fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
-                    {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
+                <div{% if not line.fields|length == 1 %} class="fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
+                    {% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
                     {% if field.is_checkbox %}
                         {{ field.field }}{{ field.label_tag }}
                     {% else %}

+ 7 - 0
django/template/defaultfilters.py

@@ -2,6 +2,7 @@
 import random as random_module
 import re
 import types
+import warnings
 from decimal import ROUND_HALF_UP, Context, Decimal, InvalidOperation
 from functools import wraps
 from inspect import unwrap
@@ -11,6 +12,7 @@ from urllib.parse import quote
 
 from django.utils import formats
 from django.utils.dateformat import format, time_format
+from django.utils.deprecation import RemovedInDjango51Warning
 from django.utils.encoding import iri_to_uri
 from django.utils.html import avoid_wrapping, conditional_escape, escape, escapejs
 from django.utils.html import json_script as _json_script
@@ -611,6 +613,11 @@ def length(value):
 @register.filter(is_safe=False)
 def length_is(value, arg):
     """Return a boolean of whether the value's length is the argument."""
+    warnings.warn(
+        "The length_is template filter is deprecated in favor of the length template "
+        "filter and the == operator within an {% if %} tag.",
+        RemovedInDjango51Warning,
+    )
     try:
         return len(value) == int(arg)
     except (ValueError, TypeError):

+ 2 - 0
docs/internals/deprecation.txt

@@ -22,6 +22,8 @@ details on these changes.
 * The ``AlterIndexTogether`` migration operation will be removed. A stub
   operation will remain for compatibility with historical migrations.
 
+* The ``length_is`` template filter will be removed.
+
 .. _deprecation-removed-in-5.0:
 
 5.0

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

@@ -1906,6 +1906,8 @@ The filter returns ``0`` for an undefined variable.
 ``length_is``
 -------------
 
+.. deprecated:: 4.2
+
 Returns ``True`` if the value's length is the argument, or ``False`` otherwise.
 
 For example::

+ 15 - 0
docs/releases/4.2.txt

@@ -317,3 +317,18 @@ Miscellaneous
   for using Python's :py:mod:`secrets` module to generate passwords.
 
 * The ``AlterIndexTogether`` migration operation is deprecated.
+
+* The ``length_is`` template filter is deprecated in favor of :tfilter:`length`
+  and the ``==`` operator within an :ttag:`{% if %}<if>` tag. For example
+
+  .. code-block:: html+django
+
+    {% if value|length == 4 %}…{% endif %}
+    {% if value|length == 4 %}True{% else %}False{% endif %}
+
+  instead of:
+
+  .. code-block:: html+django
+
+    {% if value|length_is:4 %}…{% endif %}
+    {{ value|length_is:4 }}

+ 18 - 1
tests/template_tests/filter_tests/test_length_is.py

@@ -1,9 +1,11 @@
 from django.template.defaultfilters import length_is
-from django.test import SimpleTestCase
+from django.test import SimpleTestCase, ignore_warnings
+from django.utils.deprecation import RemovedInDjango51Warning
 
 from ..utils import setup
 
 
+@ignore_warnings(category=RemovedInDjango51Warning)
 class LengthIsTests(SimpleTestCase):
     @setup({"length_is01": '{% if some_list|length_is:"4" %}Four{% endif %}'})
     def test_length_is01(self):
@@ -103,6 +105,7 @@ class LengthIsTests(SimpleTestCase):
         self.assertEqual(output, "")
 
 
+@ignore_warnings(category=RemovedInDjango51Warning)
 class FunctionTests(SimpleTestCase):
     def test_empty_list(self):
         self.assertIs(length_is([], 0), True)
@@ -111,3 +114,17 @@ class FunctionTests(SimpleTestCase):
     def test_string(self):
         self.assertIs(length_is("a", 1), True)
         self.assertIs(length_is("a", 10), False)
+
+
+class DeprecationTests(SimpleTestCase):
+    @setup(
+        {"length_is_warning": "{{ string|length_is:3 }}"},
+        test_once=True,
+    )
+    def test_length_is_warning(self):
+        msg = (
+            "The length_is template filter is deprecated in favor of the length "
+            "template filter and the == operator within an {% if %} tag."
+        )
+        with self.assertRaisesMessage(RemovedInDjango51Warning, msg):
+            self.engine.render_to_string("length_is_warning", {"string": "good"})