#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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
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