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

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.

Change History (0)

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