Opened 2 years ago
Closed 2 years ago
#33927 closed Bug (fixed)
Rendering a read-only ArrayField with choices crashes.
Reported by: | David Svenson | Owned by: | David Wobrock |
---|---|---|---|
Component: | contrib.admin | Version: | 3.2 |
Severity: | Normal | Keywords: | |
Cc: | David Wobrock | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If an ArrayField is included in an admin.ModelAdmin and has_change_permission returns False (making the field read-only), an exception is thrown when the field is supposed to be rendered.
This is the stacktrace after Django tries to render the field in django/contrib/admin/templates/admin/includes/fieldset.html
Traceback (most recent call last): File ".venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) File ".venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 204, in _get_response response = response.render() File ".venv/lib/python3.10/site-packages/django/template/response.py", line 105, in render self.content = self.rendered_content File ".venv/lib/python3.10/site-packages/django/template/response.py", line 83, in rendered_content return template.render(context, self._request) File ".venv/lib/python3.10/site-packages/django/template/backends/django.py", line 61, in render return self.template.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 170, in render return self._render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 150, in render return compiled_parent._render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 62, in render result = block.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 214, in render nodelist.append(node.render_annotated(context)) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 195, in render return template.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 172, in render return self._render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 162, in _render return self.nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 214, in render nodelist.append(node.render_annotated(context)) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 214, in render nodelist.append(node.render_annotated(context)) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 315, in render return nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 315, in render return nodelist.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 938, in render bit = node.render_annotated(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 905, in render_annotated return self.render(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 988, in render output = self.filter_expression.resolve(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 671, in resolve obj = self.var.resolve(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 796, in resolve value = self._resolve_lookup(context) File ".venv/lib/python3.10/site-packages/django/template/base.py", line 858, in _resolve_lookup current = current() File ".venv/lib/python3.10/site-packages/django/contrib/admin/helpers.py", line 239, in contents result_repr = display_for_field(value, f, self.empty_value_display) File ".venv/lib/python3.10/site-packages/django/contrib/admin/utils.py", line 385, in display_for_field return dict(field.flatchoices).get(value, empty_value_display) Exception Type: TypeError at /admin/companies/company/1/change/ Exception Value: unhashable type: 'list'
I haven't given much thought to how to solve this but I guess either contents or display_for_field has to handle the ArrayField or there should be some way to call get_FOO_display in this case.
Change History (4)
comment:1 by , 2 years ago
Summary: | Rendering an ArrayField as read-only in admin raises TypeError → Rendering a read-only ArrayField with choices crashes. |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 2 years ago
Cc: | added |
---|---|
Has patch: | set |
Owner: | changed from | to
Status: | new → assigned |
comment:3 by , 2 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Thanks for the report.
ArrayField
must havechoices
to reproduce this issue, e.g.We could try to call
make_hashable()
on theflatchoices
andvalue
:django/contrib/admin/utils.py
field.flatchoices).get(value, empty_value_display)but this can cause a performance regression.