#29637: KeyError on empty_form.fields in InlineAdminFormSet when user don't have
'add' permission for the child model
-------------------------------------+-------------------------------------
               Reporter:  Clément    |          Owner:  nobody
  Mangin                             |
                   Type:  Bug        |         Status:  new
              Component:             |        Version:  2.1
  contrib.admin                      |       Keywords:  admin, permission,
               Severity:  Normal     |  inline
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 The following use case works with Django 2.0 but breaks with Django 2.1:
 * A Parent model and a Child model with a ForeignKey to the Parent model,
 * A Parent admin form with an inline formset for adding and editing
 Children,
 * A user with change permission for the Parent and Child models, but no
 add permission for the Child model, trying to edit a Parent object and its
 children.

 The following error occurs:
 {{{
 KeyError at /admin/demo/parent/1/change/
 'name'
 Request Method: GET
 Request URL:    /admin/demo/parent/1/change/
 Django Version: 2.1
 Exception Type: KeyError
 Exception Value:
 'name'
 Exception Location:     .../python3.7/site-
 packages/django/contrib/admin/helpers.py in fields, line 287
 Python Version: 3.7.0

 Error during template rendering
 In template .../python3.7/site-
 packages/django/contrib/admin/templates/admin/edit_inline/tabular.html,
 error at line 13

 name
 3            data-inline-type="tabular"
 4            data-inline-formset="{{
 inline_admin_formset.inline_formset_data }}">
 5         <div class="tabular inline-related {% if forloop.last %}last-
 related{% endif %}">
 6       {{ inline_admin_formset.formset.management_form }}
 7       <fieldset class="module {{ inline_admin_formset.classes }}">
 8          <h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst
 }}</h2>
 9          {{ inline_admin_formset.formset.non_form_errors }}
 10         <table>
 11           <thead><tr>
 12             <th class="original"></th>
 13           {% for field in inline_admin_formset.fields %}
 14             {% if not field.widget.is_hidden %}
 15               <th{% if field.required %} class="required"{% endif %}>{{
 field.label|capfirst }}
 16               {% if field.help_text %}&nbsp;<img src="{% static
 "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10"
 height="10" alt="({{ field.help_text|striptags }})" title="{{
 field.help_text|striptags }}">{% endif %}
 17               </th>
 18             {% endif %}
 19           {% endfor %}
 20           {% if inline_admin_formset.formset.can_delete %}<th>{% trans
 "Delete?" %}</th>{% endif %}
 21           </tr></thead>
 22
 23           <tbody>
 }}}

 Trace:
 {{{
 Internal Server Error: /admin/demo/parent/1/change/
 Traceback (most recent call last):
   File ".../python3.7/site-packages/django/core/handlers/exception.py",
 line 34, in inner
     response = get_response(request)
   File ".../python3.7/site-packages/django/core/handlers/base.py", line
 156, in _get_response
     response = self.process_exception_by_middleware(e, request)
   File ".../python3.7/site-packages/django/core/handlers/base.py", line
 154, in _get_response
     response = response.render()
   File ".../python3.7/site-packages/django/template/response.py", line
 106, in render
     self.content = self.rendered_content
   File ".../python3.7/site-packages/django/template/response.py", line 83,
 in rendered_content
     content = template.render(context, self._request)
   File ".../python3.7/site-packages/django/template/backends/django.py",
 line 61, in render
     return self.template.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 171, in
 render
     return self._render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 163, in
 _render
     return self.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/loader_tags.py", line
 150, in render
     return compiled_parent._render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 163, in
 _render
     return self.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/loader_tags.py", line
 150, in render
     return compiled_parent._render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 163, in
 _render
     return self.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/loader_tags.py", line
 62, in render
     result = block.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/loader_tags.py", line
 62, in render
     result = block.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/defaulttags.py", line
 209, in render
     nodelist.append(node.render_annotated(context))
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/loader_tags.py", line
 188, in render
     return template.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 173, in
 render
     return self._render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 163, in
 _render
     return self.nodelist.render(context)
   File ".../python3.7/site-packages/django/template/base.py", line 937, in
 render
     bit = node.render_annotated(context)
   File ".../python3.7/site-packages/django/template/base.py", line 904, in
 render_annotated
     return self.render(context)
   File ".../python3.7/site-packages/django/template/defaulttags.py", line
 165, in render
     values = list(values)
   File ".../python3.7/site-packages/django/contrib/admin/helpers.py", line
 287, in fields
     form_field = empty_form.fields[field_name]
 KeyError: 'name'
 }}}

 GitHub project to see the difference in behaviour between Django 2.0 and
 Django 2.1 on this use case, using `tox`:
 https://github.com/clementmangin/django-21-error-demo

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29637>
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 post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/056.49e064d0b607d8253875faba6f130834%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to