Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion django/contrib/admin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ def lookup_field(name, obj, model_admin=None):
except (FieldDoesNotExist, FieldIsAForeignKeyColumnName):
# For non-regular field values, the value is either a method,
# property, related field, or returned via a callable.
f = None
if callable(name):
attr = name
value = attr(obj)
Expand All @@ -312,10 +313,12 @@ def lookup_field(name, obj, model_admin=None):
attr = getattr(attr, part, sentinel)
if attr is sentinel:
return None, None, None
# The final field is needed for displaying boolean icons.
if LOOKUP_SEP in name:
f = get_fields_from_path(opts.model, name)[-1]
value = attr
if hasattr(model_admin, "model") and hasattr(model_admin.model, name):
attr = getattr(model_admin.model, name)
f = None
else:
attr = None
value = getattr(obj, name)
Expand Down
2 changes: 1 addition & 1 deletion django/db/models/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2821,7 +2821,7 @@ def get_prep_value(self, value):
def get_db_prep_value(self, value, connection, prepared=False):
if value is None:
return None
if not isinstance(value, uuid.UUID):
if not prepared and not isinstance(value, uuid.UUID):
value = self.to_python(value)

if connection.features.has_native_uuid_field:
Expand Down
1 change: 1 addition & 0 deletions tests/admin_changelist/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Child(models.Model):
parent = models.ForeignKey(Parent, models.SET_NULL, editable=False, null=True)
name = models.CharField(max_length=30, blank=True)
age = models.IntegerField(null=True, blank=True)
is_active = models.BooleanField(default=True)


class GrandChild(models.Model):
Expand Down
29 changes: 29 additions & 0 deletions tests/admin_changelist/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1768,6 +1768,35 @@ class ChildAdmin(admin.ModelAdmin):
cl = m.get_changelist_instance(request)
self.assertEqual(cl.get_ordering_field_columns(), {2: "asc"})

def test_list_display_related_field_boolean_display(self):
"""
Related boolean fields (parent__is_active) display boolean icons.
"""
parent = Parent.objects.create(name="Test Parent")
child_active = Child.objects.create(
name="Active Child", parent=parent, is_active=True
)
child_inactive = Child.objects.create(
name="Inactive Child", parent=parent, is_active=False
)

class GrandChildAdmin(admin.ModelAdmin):
list_display = ["name", "parent__is_active"]

GrandChild.objects.create(name="GrandChild of Active", parent=child_active)
GrandChild.objects.create(name="GrandChild of Inactive", parent=child_inactive)

m = GrandChildAdmin(GrandChild, custom_site)
request = self._mocked_authenticated_request("/grandchild/", self.superuser)
response = m.changelist_view(request)

# Boolean icons are rendered using img tags with specific alt text.
self.assertContains(response, 'alt="True"')
self.assertContains(response, 'alt="False"')
# Ensure "True" and "False" text are NOT in the response.
self.assertNotContains(response, ">True<")
self.assertNotContains(response, ">False<")


class GetAdminLogTests(TestCase):
def test_custom_user_pk_not_named_id(self):
Expand Down
4 changes: 4 additions & 0 deletions tests/prefetch_related/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ class CustomUUIDField(models.UUIDField):
def get_prep_value(self, value):
return str(value)

def get_db_prep_value(self, value, connection, prepared=False):
# Use prepared=False to ensure str -> UUID conversion is performed.
return super().get_db_prep_value(value, connection, prepared=False)

id = CustomUUIDField(primary_key=True, default=uuid.uuid4)
name = models.CharField(max_length=30)

Expand Down
Loading