Browse Source

Fixed #31558 -- Added support for boolean attribute on properties in ModelAdmin.list_display.

Ryanwalker277 1 year ago
parent
commit
225328efd9

+ 3 - 0
django/contrib/admin/templatetags/admin_list.py

@@ -225,6 +225,9 @@ def items_for_result(cl, result, form):
                 if field_name == "action_checkbox":
                     row_classes = ["action-checkbox"]
                 boolean = getattr(attr, "boolean", False)
+                # Set boolean for attr that is a property, if defined.
+                if isinstance(attr, property) and hasattr(attr, "fget"):
+                    boolean = getattr(attr.fget, "boolean", False)
                 result_repr = display_for_value(value, empty_value_display, boolean)
                 if isinstance(value, (datetime.date, datetime.time)):
                     row_classes.append("nowrap")

+ 2 - 0
django/contrib/admin/utils.py

@@ -302,6 +302,8 @@ def lookup_field(name, obj, model_admin=None):
                 value = attr()
             else:
                 value = attr
+            if hasattr(model_admin, "model") and hasattr(model_admin.model, name):
+                attr = getattr(model_admin.model, name)
         f = None
     else:
         attr = None

+ 6 - 0
docs/ref/contrib/admin/index.txt

@@ -796,6 +796,7 @@ subclass::
               @admin.display(
                   ordering="last_name",
                   description="Full name of the person",
+                  boolean=False,
               )
               def full_name(self):
                   return self.first_name + " " + self.last_name
@@ -816,9 +817,14 @@ subclass::
 
           my_property.short_description = "Full name of the person"
           my_property.admin_order_field = "last_name"
+          my_property.boolean = False
 
           full_name = property(my_property)
 
+      .. versionchanged:: 5.0
+
+        Support for ``boolean`` attribute on properties was added.
+
     * The field names in ``list_display`` will also appear as CSS classes in
       the HTML output, in the form of ``column-<field_name>`` on each ``<th>``
       element. This can be used to set column widths in a CSS file for example.

+ 3 - 0
docs/releases/5.0.txt

@@ -211,6 +211,9 @@ Minor features
 * The new :meth:`.AdminSite.get_model_admin` method returns an admin class for
   the given model class.
 
+* Properties in :attr:`.ModelAdmin.list_display` now support ``boolean``
+  attribute.
+
 :mod:`django.contrib.admindocs`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

+ 1 - 0
tests/admin_views/admin.py

@@ -216,6 +216,7 @@ class ArticleAdmin(ArticleAdminWithExtraUrl):
         "model_month",
         "order_by_f_expression",
         "order_by_orderby_expression",
+        "model_property_is_from_past",
     )
     list_editable = ("section",)
     list_filter = ("date", "section")

+ 6 - 0
tests/admin_views/models.py

@@ -9,6 +9,7 @@ from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
 from django.core.files.storage import FileSystemStorage
 from django.db import models
+from django.utils import timezone
 
 
 class Section(models.Model):
@@ -66,6 +67,11 @@ class Article(models.Model):
     def model_month(self):
         return self.date.month
 
+    @property
+    @admin.display(description="Is from past?", boolean=True)
+    def model_property_is_from_past(self):
+        return self.date < timezone.now()
+
 
 class Book(models.Model):
     """

+ 8 - 0
tests/admin_views/tests.py

@@ -486,6 +486,14 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
             "Results of sorting on callable are out of order.",
         )
 
+    def test_change_list_boolean_display_property(self):
+        response = self.client.get(reverse("admin:admin_views_article_changelist"))
+        self.assertContains(
+            response,
+            '<td class="field-model_property_is_from_past">'
+            '<img src="/static/admin/img/icon-yes.svg" alt="True"></td>',
+        )
+
     def test_change_list_sorting_property(self):
         """
         Sort on a list_display field that is a property (column 10 is