Opened 4 years ago
Last modified 3 years ago
#31867 closed Bug
Inconsistency in rendering hidden fields in Django admin — at Initial Version
Reported by: | Antoine Humbert | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | 2.1 |
Severity: | Normal | Keywords: | admin hidden field |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | yes |
Description
In django admin, when having an inline ModelAdmin with a hidden widget (e.g. "position" field when using sortable inlines with django_nested_admin or grappelli), the field may be rendered in admin interface depending on context:
- when user has change permission on the model, the field is not shown (because is has an HiddenInput widget)
- when user has view permission, but not change permission:
- If field is in a StackedInline and is the only field on a line (e.g. fields = ("field1", "field2", "hidden_field") or fields = (("field1", "field2"), "hidden_field")), then field does not appear in admin interface
- => this is due to the row having the hidden class (coming from django.contrib.admin.helpers.Fieldline.has_visible_field which is False, because it is evaluated according to the field widget - which is HiddenInput). The <div> containing field value itself does not have the hidden class.
- If field is in a StackedInline and is not the only field on a line (e.g. fields = ("field1", ("field2", "hidden_field"))), then field appear in admin interface
- => this time, the row does not have the hidden class, because not all fields of the line are hidden
- If field is in a TabularInline, then field appear in the admin interface
- => There is no django.contrig.admin.helpers.Fieldline in this case which may hide a row containing the field
- If field is in a StackedInline and is the only field on a line (e.g. fields = ("field1", "field2", "hidden_field") or fields = (("field1", "field2"), "hidden_field")), then field does not appear in admin interface
The inconsistency resided in the fact that django.contrib.admin.helpers.Fieldline.has_visible_field rely on the field widget.is_hidden (whatever user has change permission on the model or nat), whereas in django.contrib.admin.helpers.InlineAdminFormset.fields, if user has change permission, field is rendered using the field widget (HiddenInput in this case), but is user does not have change permission, field widget is statically defined with {'hidden': False}.
In this function, changing lines
if not self.has_change_permission or field_name in self.readonly_fields: yield { 'name': field_name, 'label': meta_labels.get(field_name) or label_for_field( field_name, self.opts.model, self.opts, form=empty_form, ), 'widget': {'is_hidden': False}, 'required': False, 'help_text': meta_help_texts.get(field_name) or help_text_for_field(field_name, self.opts.model), }
to
if not self.has_change_permission or field_name in self.readonly_fields: yield { 'name': field_name, 'label': meta_labels.get(field_name) or label_for_field( field_name, self.opts.model, self.opts, form=empty_form, ), 'widget': {'is_hidden': empty_form.fields[field_name].widget.is_hidden}, 'required': False, 'help_text': meta_help_texts.get(field_name) or help_text_for_field(field_name, self.opts.model), }
effectively hides the field.
I produce the bug in version 2.1, but I expect it to be present is newer versions as the implied code is the same.