Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#33547 closed Bug (fixed)

Admin TabularInline with readonly field fail to render on validation error

Reported by: David Glenck Owned by: Mariusz Felisiak
Component: contrib.admin Version: 4.0
Severity: Release blocker Keywords: tabularinline readonly
Cc: Antoine Humbert 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

Error Message "'dict' object has no attribute 'is_hidden'"
In this line https://github.com/django/django/blob/e0442a628eb480eac6a7888aed5a86f83499e299/django/contrib/admin/templatetags/admin_modify.py#L141
Here in the template https://github.com/django/django/blob/e0442a628eb480eac6a7888aed5a86f83499e299/django/contrib/admin/templates/admin/edit_inline/tabular.html#L28

In my case the reasong is that the field in the inline is readonly which makes it a dict without the "is_hidden" attribute.

Code to reproduce.
Model:

class MyModel(models.Model):
    other_model = models.ForeignKey('OtherModel', on_delete=models.CASCADE)

    def clean(self):
        raise ValidationError()

Inline:

class MyModelInline(admin.TabularInline):
    model = MyModel
    readonly_fields = ['my_readonly_field']

    @admin.display(description='MyReadonlyField')
    def my_readonly_field(self, instance):
        return 'value'

Then using this tabular inline in OtherModelAdmin.
Trying to add a new MyModel in OtherModel via admin will raise the ValidationError and consequently cause this issue.

Changing this line https://github.com/django/django/blob/e0442a628eb480eac6a7888aed5a86f83499e299/django/contrib/admin/templatetags/admin_modify.py#L141 to:

if not getattr(field.field, 'is_hidden', False):

Seems to fix the issue.

Change History (7)

in reply to:  description comment:1 by Mariusz Felisiak, 2 years ago

Cc: Antoine Humbert added
Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

Thanks for the report.

Changing this line https://github.com/django/django/blob/e0442a628eb480eac6a7888aed5a86f83499e299/django/contrib/admin/templatetags/admin_modify.py#L141 to:

if not getattr(field.field, 'is_hidden', False):

Seems to fix the issue

field dictionary for AdminReadonlyField has the is_hidden key so we should use it instead of assuming it's False.

Regression in de95c826673be9ea519acc86fd898631d1a11356.
Reproduces at e0442a628eb480eac6a7888aed5a86f83499e299.

comment:2 by Mariusz Felisiak, 2 years ago

Owner: changed from nobody to Mariusz Felisiak
Status: newassigned

comment:3 by Mariusz Felisiak, 2 years ago

Has patch: set

comment:4 by Carlton Gibson, 2 years ago

Triage Stage: AcceptedReady for checkin

comment:5 by GitHub <noreply@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In 445b075d:

Fixed #33547 -- Fixed error when rendering invalid inlines with readonly fields in admin.

Regression in de95c826673be9ea519acc86fd898631d1a11356.

Thanks David Glenck for the report.

comment:6 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

In 82f25266:

[4.0.x] Fixed #33547 -- Fixed error when rendering invalid inlines with readonly fields in admin.

Regression in de95c826673be9ea519acc86fd898631d1a11356.

Thanks David Glenck for the report.
Backport of 445b075def2c037b971518963b70ce13df5e88a2 from main

comment:7 by Antoine Humbert, 2 years ago

May be a bit late now, but I think the original reason for this kind of bug is because of API inconsistency between AdminReadonlyField and AdminField where .field attribute is a dict (with keys) for the former and a BoundField (with attributes) for the latter.
The difference works as soon as it is used in templates because object attributes and dict keys are accessed using the same syntax. But as soon as it is used in python code (like in reported bug), it breaks. Making .field a namedtuple or a dataclass in AdminReadonlyField would have solve the problem (without hurting usage in templates) without requiring some exceptions management, and would also make things easier to manage if .field is used somewhere else in python code.

What do you think about this ?

Note: See TracTickets for help on using tickets.
Back to Top