[Django] #37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a relation field (regression from #36926)

10 views
Skip to first unread message

Django

unread,
Jul 25, 2026, 10:46:18 AM (4 days ago) Jul 25
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
----------------------------+-------------------------------------------
Reporter: RobKuipers | Type: Bug
Status: new | Component: contrib.admin
Version: dev | Severity: Release blocker
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+-------------------------------------------
Since #36926, `list_display` entries using `__` lookup syntax to traverse
related fields (documented at
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display)
raise `AttributeError` when the *final* segment of the path is itself a
relation field (ForeignKey/OneToOneField), rather than a scalar field.

This worked correctly before #36926 and is not limited to any unusual
setup — any `related__fk_field` entry regresses.

=== Minimal reproduction ===

{{{#!python
class Publisher(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
title = models.CharField(max_length=100)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

class Author(models.Model):
name = models.CharField(max_length=100)
book = models.ForeignKey(Book, on_delete=models.CASCADE)

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ["name", "book__publisher"]
}}}

Visiting the `Author` changelist with at least one row raises:

{{{
AttributeError: 'Author' object has no attribute 'publisher'
}}}

=== Root cause ===

#36926 added this to `lookup_field()` in `django/contrib/admin/utils.py`,
specifically to let `display_for_field()` recognize `BooleanField`s
reached
via a `__` path so it can render the boolean icon:

{{{#!python
# The final field is needed for displaying boolean
icons.
if LOOKUP_SEP in name:
f = get_fields_from_path(opts.model, name)[-1]
}}}

This sets `f` unconditionally whenever the path contains `LOOKUP_SEP`, not
only when the terminal field is a `BooleanField`. Previously, `f` stayed
`None` for this whole branch (the "method, property, related field, or
callable" fallback), and `items_for_result()` in
`django/contrib/admin/templatetags/admin_list.py` used the already
correctly-traversed `value` via `display_for_value()`.

Now that `f` is non-`None`, `items_for_result()` takes a different branch
that assumes `f` is a field belonging to `result` directly:

{{{#!python
else:
if isinstance(f.remote_field, models.ManyToOneRel):
field_val = getattr(result, f.name)
}}}

That assumption holds for the normal case (`list_display = ["publisher"]`
where `publisher` really is a field on the model being rendered), but not
for the `__`-traversal case, where `f` is a field on the *related* model
several hops down the path — `result` (an `Author`) has no `publisher`
attribute; `result.book` does.

=== Suggested fix direction ===

Scope the new `f` assignment to its stated purpose — only set it when the
terminal field is actually a `BooleanField` — rather than for every
`LOOKUP_SEP`-containing path:

{{{#!python
if LOOKUP_SEP in name:
final_field = get_fields_from_path(opts.model,
name)[-1]
if isinstance(final_field, models.BooleanField):
f = final_field
}}}

This preserves the boolean-icon feature #36926 added while restoring the
pre-6.1 (and documented) behavior for `__` paths ending in any other field
type, including relations.

I have not attempted a full patch/tests — that's a little out of my league
I'm afraid.
--
Ticket URL: <https://code.djangoproject.com/ticket/37230>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 26, 2026, 4:10:04 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+------------------------------------
Reporter: RobKuipers | Owner: (none)
Type: Bug | Status: new
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+------------------------------------
Changes (by David Smith):

* stage: Unreviewed => Accepted

Comment:

I was able to replicate this issue and saw that the behaviour changed in
4b2b4bf0ac2707dc9c4d51cabfa72168eaea95fe. Given this is a new change for
6.1 the triage state of release blocker seems right to me.
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:1>

Django

unread,
Jul 26, 2026, 7:26:22 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Zubair Hassan):

* owner: (none) => Zubair Hassan
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:2>

Django

unread,
Jul 26, 2026, 7:43:59 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Zubair Hassan):

* has_patch: 0 => 1

Comment:

https://github.com/django/django/pull/21673
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:3>

Django

unread,
Jul 26, 2026, 10:57:10 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Clifford Gama):

* needs_tests: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:4>

Django

unread,
Jul 26, 2026, 10:57:58 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 1 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Clifford Gama):

* needs_docs: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:5>

Django

unread,
Jul 26, 2026, 11:01:28 AM (3 days ago) Jul 26
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Clifford Gama):

* needs_docs: 1 => 0

Comment:

Patch is missing regression tests. (No docs changes required, please
ignore the changes to that ticket flag.)
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:6>

Django

unread,
Jul 27, 2026, 1:30:23 AM (3 days ago) Jul 27
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Comment (by Zubair Hassan):

Added regression tests.
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:7>

Django

unread,
Jul 27, 2026, 3:58:01 AM (2 days ago) Jul 27
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Sarah Boyce):

* version: dev => 6.1

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:8>

Django

unread,
Jul 27, 2026, 10:20:48 AM (2 days ago) Jul 27
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
---------------------------------+-----------------------------------------
Reporter: RobKuipers | Owner: Zubair Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
---------------------------------+-----------------------------------------
Changes (by Jacob Walls):

* needs_better_patch: 0 => 1
* needs_tests: 1 => 0

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:9>

Django

unread,
Jul 28, 2026, 10:41:25 AM (yesterday) Jul 28
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
-------------------------------------+-------------------------------------
Reporter: RobKuipers | Owner: Zubair
| Hassan
Type: Bug | Status: assigned
Component: contrib.admin | Version: 6.1
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* needs_better_patch: 1 => 0
* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:10>

Django

unread,
Jul 28, 2026, 2:09:49 PM (yesterday) Jul 28
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
-------------------------------------+-------------------------------------
Reporter: RobKuipers | Owner: Zubair
| Hassan
Type: Bug | Status: closed
Component: contrib.admin | Version: 6.1
Severity: Release blocker | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls <jacobtylerwalls@…>):

* resolution: => fixed
* status: assigned => closed

Comment:

In [changeset:"92470ad3742524902b29769d2c822dbe791630db" 92470ad3]:
{{{#!CommitTicketReference repository=""
revision="92470ad3742524902b29769d2c822dbe791630db"
Fixed #37230 -- Fixed a crash for second-degree relations in
ModelAdmin.list_display.

Thanks Rob Kuipers for the report.

Regression in 4b2b4bf0ac2707dc9c4d51cabfa72168eaea95fe.

Co-authored-by: Jacob Walls <jacobty...@gmail.com>
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:11>

Django

unread,
Jul 28, 2026, 2:11:27 PM (yesterday) Jul 28
to django-...@googlegroups.com
#37230: ModelAdmin.list_display: AttributeError when a __ lookup path ends in a
relation field (regression from #36926)
-------------------------------------+-------------------------------------
Reporter: RobKuipers | Owner: Zubair
| Hassan
Type: Bug | Status: closed
Component: contrib.admin | Version: 6.1
Severity: Release blocker | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Jacob Walls <jacobtylerwalls@…>):

In [changeset:"724d876038abbaca306cd2813fb74d952c1d096e" 724d8760]:
{{{#!CommitTicketReference repository=""
revision="724d876038abbaca306cd2813fb74d952c1d096e"
[6.1.x] Fixed #37230 -- Fixed a crash for second-degree relations in
ModelAdmin.list_display.

Thanks Rob Kuipers for the report.

Regression in 4b2b4bf0ac2707dc9c4d51cabfa72168eaea95fe.

Co-authored-by: Jacob Walls <jacobty...@gmail.com>

Backport of 92470ad3742524902b29769d2c822dbe791630db from main.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/37230#comment:12>
Reply all
Reply to author
Forward
0 new messages