#31867: Inconsistency in rendering hidden fields in Django admin
------------------------------------+--------------------------------------
     Reporter:  Antoine Humbert     |                    Owner:  nobody
         Type:  Bug                 |                   Status:  new
    Component:  contrib.admin       |                  Version:  2.1
     Severity:  Normal              |               Resolution:
     Keywords:  admin hidden field  |             Triage Stage:  Unreviewed
    Has patch:  1                   |      Needs documentation:  0
  Needs tests:  0                   |  Patch needs improvement:  0
Easy pickings:  0                   |                    UI/UX:  1
------------------------------------+--------------------------------------
Description changed by Antoine Humbert:

Old 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.

New 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),
                 }

 }}}

 will hide the table column header for the hidden field. Unfortunatly, it
 does not hide the fields values theselves (I'll try to find a workaround
 for that)

 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.

--

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

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/072.d35171ba50c3808bb41305bc42429de7%40djangoproject.com.

Reply via email to