浏览代码

Fixed #28404 -- Made displaying values in admin respect Field's empty_values.

Alexander Lazarević 1 年之前
父节点
当前提交
9b02ad91ea
共有 5 个文件被更改,包括 37 次插入11 次删除
  1. 1 0
      AUTHORS
  2. 1 1
      django/contrib/admin/utils.py
  3. 28 6
      tests/admin_changelist/tests.py
  4. 6 3
      tests/admin_utils/tests.py
  5. 1 1
      tests/admin_widgets/tests.py

+ 1 - 0
AUTHORS

@@ -47,6 +47,7 @@ answer newbie questions, and generally made Django that much better:
     Aleksandra Sendecka <asendecka@hauru.eu>
     Aleksi Häkli <aleksi.hakli@iki.fi>
     Alex Dutton <django@alexdutton.co.uk>
+    Alexander Lazarević <laza@e11bits.com>
     Alexander Myodov <alex@myodov.com>
     Alexandr Tatarinov <tatarinov.dev@gmail.com>
     Alex Aktsipetrov <alex.akts@gmail.com>

+ 1 - 1
django/contrib/admin/utils.py

@@ -433,7 +433,7 @@ def display_for_field(value, field, empty_value_display):
     # general null test.
     elif isinstance(field, models.BooleanField):
         return _boolean_icon(value)
-    elif value is None:
+    elif value in field.empty_values:
         return empty_value_display
     elif isinstance(field, models.DateTimeField):
         return formats.localize(timezone.template_localtime(value))

+ 28 - 6
tests/admin_changelist/tests.py

@@ -74,15 +74,15 @@ from .models import (
 )
 
 
-def build_tbody_html(obj, href, extra_fields):
+def build_tbody_html(obj, href, field_name, extra_fields):
     return (
         "<tbody><tr>"
         '<td class="action-checkbox">'
         '<input type="checkbox" name="_selected_action" value="{}" '
         'class="action-select" aria-label="Select this object for an action - {}"></td>'
-        '<th class="field-name"><a href="{}">name</a></th>'
+        '<th class="field-name"><a href="{}">{}</a></th>'
         "{}</tr></tbody>"
-    ).format(obj.pk, str(obj), href, extra_fields)
+    ).format(obj.pk, str(obj), href, field_name, extra_fields)
 
 
 @override_settings(ROOT_URLCONF="admin_changelist.urls")
@@ -245,7 +245,7 @@ class ChangeListTests(TestCase):
         table_output = template.render(context)
         link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
         row_html = build_tbody_html(
-            new_child, link, '<td class="field-parent nowrap">-</td>'
+            new_child, link, "name", '<td class="field-parent nowrap">-</td>'
         )
         self.assertNotEqual(
             table_output.find(row_html),
@@ -253,6 +253,24 @@ class ChangeListTests(TestCase):
             "Failed to find expected row element: %s" % table_output,
         )
 
+    def test_result_list_empty_changelist_value_blank_string(self):
+        new_child = Child.objects.create(name="", parent=None)
+        request = self.factory.get("/child/")
+        request.user = self.superuser
+        m = ChildAdmin(Child, custom_site)
+        cl = m.get_changelist_instance(request)
+        cl.formset = None
+        template = Template(
+            "{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}"
+        )
+        context = Context({"cl": cl, "opts": Child._meta})
+        table_output = template.render(context)
+        link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
+        row_html = build_tbody_html(
+            new_child, link, "-", '<td class="field-parent nowrap">-</td>'
+        )
+        self.assertInHTML(row_html, table_output)
+
     def test_result_list_set_empty_value_display_on_admin_site(self):
         """
         Empty value display can be set on AdminSite.
@@ -272,7 +290,7 @@ class ChangeListTests(TestCase):
         table_output = template.render(context)
         link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
         row_html = build_tbody_html(
-            new_child, link, '<td class="field-parent nowrap">???</td>'
+            new_child, link, "name", '<td class="field-parent nowrap">???</td>'
         )
         self.assertNotEqual(
             table_output.find(row_html),
@@ -299,6 +317,7 @@ class ChangeListTests(TestCase):
         row_html = build_tbody_html(
             new_child,
             link,
+            "name",
             '<td class="field-age_display">&amp;dagger;</td>'
             '<td class="field-age">-empty-</td>',
         )
@@ -327,7 +346,10 @@ class ChangeListTests(TestCase):
         table_output = template.render(context)
         link = reverse("admin:admin_changelist_child_change", args=(new_child.id,))
         row_html = build_tbody_html(
-            new_child, link, '<td class="field-parent nowrap">%s</td>' % new_parent
+            new_child,
+            link,
+            "name",
+            '<td class="field-parent nowrap">%s</td>' % new_parent,
         )
         self.assertNotEqual(
             table_output.find(row_html),

+ 6 - 3
tests/admin_utils/tests.py

@@ -159,9 +159,12 @@ class UtilsTests(SimpleTestCase):
             models.TimeField(),
         ]
         for model_field in tests:
-            with self.subTest(model_field=model_field):
-                display_value = display_for_field(None, model_field, self.empty_value)
-                self.assertEqual(display_value, self.empty_value)
+            for value in model_field.empty_values:
+                with self.subTest(model_field=model_field, empty_value=value):
+                    display_value = display_for_field(
+                        value, model_field, self.empty_value
+                    )
+                    self.assertEqual(display_value, self.empty_value)
 
     def test_empty_value_display_choices(self):
         model_field = models.CharField(choices=((None, "test_none"),))

+ 1 - 1
tests/admin_widgets/tests.py

@@ -641,7 +641,7 @@ class AdminFileWidgetTests(TestDataMixin, TestCase):
         response = self.client.get(reverse("admin:admin_widgets_album_add"))
         self.assertContains(
             response,
-            '<div class="readonly"></div>',
+            '<div class="readonly">-</div>',
             html=True,
         )