[Django] #34481: Admin check for reversed foreign key used in "list_display"

8 views
Skip to first unread message

Django

unread,
Apr 10, 2023, 3:35:48 PM4/10/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
------------------------------------------+------------------------
Reporter: Natalia Bidart | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: dev
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------+------------------------
Currently the admin site checks and reports an `admin.E109` system check
error when a `ManyToManyField` is declared within the `list_display`
values.
But, when a reversed foreign key is used there is no system error
reported:

{{{
System check identified no issues (0 silenced).
April 10, 2023 - 19:04:29
Django version 5.0.dev20230410064954, using settings
'projectfromrepo.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
}}}

and visiting the admin site for the relevant model results in the
following error:

{{{
TypeError:
create_reverse_many_to_one_manager.<locals>.RelatedManager.__call__()
missing 1 required keyword-only argument: 'manager'
[10/Apr/2023 19:30:40] "GET /admin/testapp/question/ HTTP/1.1" 500 415926
}}}

Ideally, using a reversed foreign key would also result in a system check
error instead of a 500 response.

To reproduce, follow the `Question` and `Choice` models from the Django
Tutorial and add the following to the `QuestionAdmin`:

{{{
list_display = ["question_text", "choice_set"]
}}}

Then, visit `/admin/testapp/question/` and the following traceback is
returned:

{{{
Internal Server Error: /admin/testapp/question/
Traceback (most recent call last):
File "/some/path/django/django/db/models/options.py", line 681, in
get_field
return self.fields_map[field_name]
~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'choice_set'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/some/path/django/django/contrib/admin/utils.py", line 288, in
lookup_field
f = _get_non_gfk_field(opts, name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/contrib/admin/utils.py", line 319, in
_get_non_gfk_field
field = opts.get_field(name)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/db/models/options.py", line 683, in
get_field
raise FieldDoesNotExist(
django.core.exceptions.FieldDoesNotExist: Question has no field named
'choice_set'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/some/path/django/django/core/handlers/exception.py", line 55, in
inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/core/handlers/base.py", line 220, in
_get_response
response = response.render()
^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/response.py", line 111, in
render
self.content = self.rendered_content
^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/response.py", line 89, in
rendered_content
return template.render(context, self._request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/backends/django.py", line 61, in
render
return self.template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 171, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 163, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in
<listcomp>
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 962, in
render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/loader_tags.py", line 157, in
render
return compiled_parent._render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 163, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in
<listcomp>
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 962, in
render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/loader_tags.py", line 157, in
render
return compiled_parent._render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 163, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in
<listcomp>
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 962, in
render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/loader_tags.py", line 63, in
render
result = block.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in
<listcomp>
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 962, in
render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/loader_tags.py", line 63, in
render
result = block.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in render
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 1001, in
<listcomp>
return SafeString("".join([node.render_annotated(context) for node in
self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/base.py", line 962, in
render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/contrib/admin/templatetags/base.py", line
45, in render
return super().render(context)
^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/template/library.py", line 258, in render
_dict = self.func(*resolved_args, **resolved_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/some/path/django/django/contrib/admin/templatetags/admin_list.py", line
340, in result_list
"results": list(results(cl)),
^^^^^^^^^^^^^^^^^
File
"/some/path/django/django/contrib/admin/templatetags/admin_list.py", line
316, in results
yield ResultList(None, items_for_result(cl, res, None))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/some/path/django/django/contrib/admin/templatetags/admin_list.py", line
307, in __init__
super().__init__(*items)
File
"/some/path/django/django/contrib/admin/templatetags/admin_list.py", line
217, in items_for_result
f, attr, value = lookup_field(field_name, result, cl.model_admin)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/some/path/django/django/contrib/admin/utils.py", line 301, in
lookup_field
value = attr()
^^^^^^
TypeError:
create_reverse_many_to_one_manager.<locals>.RelatedManager.__call__()
missing 1 required keyword-only argument: 'manager'
[10/Apr/2023 19:30:40] "GET /admin/testapp/question/ HTTP/1.1" 500 415926
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/34481>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 10, 2023, 11:29:31 PM4/10/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+------------------------------------

Reporter: Natalia Bidart | Owner: nobody
Type: Bug | Status: new
Component: contrib.admin | Version: dev
Severity: Normal | 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 Mariusz Felisiak):

* type: Uncategorized => Bug
* component: Uncategorized => contrib.admin
* stage: Unreviewed => Accepted


Comment:

Thanks for the report.

--
Ticket URL: <https://code.djangoproject.com/ticket/34481#comment:1>

Django

unread,
Apr 12, 2023, 7:18:29 AM4/12/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+------------------------------------
Reporter: Natalia Bidart | Owner: nobody
Type: Bug | Status: new
Component: contrib.admin | Version: dev
Severity: Normal | 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 Bakdolot):

* cc: Bakdolot (added)


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

Django

unread,
Apr 12, 2023, 7:19:14 AM4/12/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+------------------------------------
Reporter: Natalia Bidart | Owner: Bakdolot
Type: Bug | Status: assigned

Component: contrib.admin | Version: dev
Severity: Normal | 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 Bakdolot):

* owner: nobody => Bakdolot
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/34481#comment:3>

Django

unread,
Apr 12, 2023, 11:10:47 AM4/12/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+------------------------------------
Reporter: Natalia Bidart | Owner: Bakdolot
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------+------------------------------------

Comment (by Bakdolot):

[https://github.com/django/django/pull/16531 PR]

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

Django

unread,
Apr 14, 2023, 4:07:13 AM4/14/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+-----------------------------------------
Reporter: Natalia Bidart | Owner: Baha Sdtbekov

Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Normal | 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 Mariusz Felisiak):

* has_patch: 0 => 1


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

Django

unread,
Apr 20, 2023, 12:46:53 PM4/20/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
--------------------------------+-----------------------------------------
Reporter: Natalia Bidart | Owner: Baha Sdtbekov
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 1
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
--------------------------------+-----------------------------------------
Changes (by Natalia Bidart):

* needs_better_patch: 0 => 1
* needs_docs: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/34481#comment:6>

Django

unread,
Apr 24, 2023, 5:49:46 AM4/24/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
-------------------------------------+-------------------------------------

Reporter: Natalia Bidart | Owner: Baha
| Sdtbekov
Type: Bug | Status: assigned
Component: contrib.admin | Version: dev
Severity: Normal | 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 Mariusz Felisiak):

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


--
Ticket URL: <https://code.djangoproject.com/ticket/34481#comment:7>

Django

unread,
Apr 24, 2023, 7:14:54 AM4/24/23
to django-...@googlegroups.com
#34481: Admin check for reversed foreign key used in "list_display"
-------------------------------------+-------------------------------------
Reporter: Natalia Bidart | Owner: Baha
| Sdtbekov
Type: Bug | Status: closed
Component: contrib.admin | Version: dev
Severity: Normal | 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 GitHub <noreply@…>):

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


Comment:

In [changeset:"c813fb327cb1b09542be89c5ceed367826236bc2" c813fb3]:
{{{
#!CommitTicketReference repository=""
revision="c813fb327cb1b09542be89c5ceed367826236bc2"
Fixed #34481 -- Added system check for reverse related fields in
ModelAdmin.list_display.
}}}

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

Reply all
Reply to author
Forward
0 new messages