Opened 3 weeks ago
Last modified 8 days ago
#36926 assigned Cleanup/optimization
Admin list_display does not use boolean icons when traversing relations
| Reported by: | Michael Nagler | Owned by: | Huwaiza |
|---|---|---|---|
| Component: | contrib.admin | Version: | 6.0 |
| Severity: | Normal | Keywords: | |
| Cc: | Huwaiza, Brian Helba | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | yes |
Description
I have a UserProfile model that I am attempting to inline into the User admin page.
I want to show an additional column in the User admin denoting the value of UserProfile.verified. I can successfully add this column by appending 'profile__verified' the list_display property of my custom UserAdmin class, however the value that shows up in the column is either the string "True" or "False".
It would be great if adding 'profile__verified' to the list_display of the admin class could detect that the field is a boolean (it is indeed an instance of models.BooleanField on the UserProfile), and display the icons.
My current workaround is to define a callable on my custom admin class and mark it as a boolean with the admin.display decorator.
For reference, here is the model and admin class that produce the undesirable behavior:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
verified = models.BooleanField(default=False)
@admin.register(User)
class UserAdmin(BaseUserAdmin):
inlines = [UserProfileInline]
list_select_related = ['profile']
list_display = list(BaseUserAdmin.list_display) + ['profile__verified']
list_filter = list(BaseUserAdmin.list_filter) + ['profile__verified']
Change History (9)
comment:1 by , 2 weeks ago
| Cc: | added |
|---|---|
| Owner: | set to |
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Ready for checkin |
comment:2 by , 2 weeks ago
| Type: | Uncategorized → New feature |
|---|
comment:3 by , 2 weeks ago
| Has patch: | set |
|---|---|
| UI/UX: | set |
comment:4 by , 2 weeks ago
| Triage Stage: | Ready for checkin → Unreviewed |
|---|
comment:5 by , 2 weeks ago
Thank you for the suggestion Huwaiza!
Correct me if I'm wrong, but are you saying that when a field is a BooleanField, it should automatically be displayed as an icon without needing to use admin.display(boolean=True)?
Are there any cases where displaying it as plain text would be useful?
comment:6 by , 2 weeks ago
Yes, that is exactly right. When a field is a direct BooleanField on the model for example
list_display = ['is_active']
Django already automatically displays it as a boolean icon, no @admin.display(boolean=True) needed.
This is handled in display_for_field() in django/contrib/admin/utils.py:
elif isinstance(field, models.BooleanField):
return _boolean_icon(value)
The bug is specifically about related field traversal. When you write profile__verified instead of verified, Django cannot find the field via _get_non_gfk_field() because the name contains __, so it falls back to f=None. With f=None, it calls display_for_value() instead of display_for_field(), which simply returns str(value) → "True"/"False".
This fix closes that gap: when traversing a relation path with __, we resolve the final field using get_fields_from_path() and pass it as f, so display_for_field() is called correctly and the same automatic boolean icon behavior that exists for direct fields is preserved.
Regarding your question about plain text being useful, No, there is no case where a BooleanField should display as plain text in the changelist. Django already makes this decision unconditionally for direct BooleanFields, the fix simply extends that same existing behavior to related field traversal for consistency.
comment:7 by , 2 weeks ago
| Cc: | added |
|---|
comment:8 by , 8 days ago
| Summary: | Admin list_display does not use boolean icons when traversing properties → Admin list_display does not use boolean icons when traversing relations |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Type: | New feature → Cleanup/optimization |
Seems conceptually similar to #19963 in terms of removing inconsistency. Having a series of booleans mixed between local models and related models would create an inconsistent row of "X, True, X, True, ..." etc.
comment:9 by , 8 days ago
| Patch needs improvement: | set |
|---|
PR link: https://github.com/django/django/pull/20718