#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 resides in the fact that
> django.contrib.admin.helpers.Fieldline.has_visible_field relies on the
> field widget.is_hidden (whatever user has change permission on the model
> or not), 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 if 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.
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 resides in the fact that
django.contrib.admin.helpers.Fieldline.has_visible_field relies on the
field widget.is_hidden (whatever user has change permission on the model
or not), 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 if 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 themelves (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:4>
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.cb125ce5c1f32a8ed38de159c2a194c1%40djangoproject.com.