Opened 6 years ago

Last modified 6 years ago

#29701 closed Bug

has_add_permission in admin.TabularInline gives KeyError exception — at Version 2

Reported by: Harm Verhagen Owned by: nobody
Component: contrib.admin Version: 2.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Harm Verhagen)

I noticed that using has_add_permission() on a admin.TabularInline fails.

See the simple example below.

steps to reproduce

models.py

class ModelA(models.Model):
    name = models.CharField(max_length=2)
    bs = models.ManyToManyField("ModelB", through="Through")

    def __str__(self):
        return "%s" % self.name

class ModelB(models.Model):
    name = models.CharField(max_length=2)

    def __str__(self):
        return "%s" % self.name

class Through(models.Model):
    a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
    b = models.ForeignKey(ModelB, on_delete=models.CASCADE)

    def __str__(self):
        return "%s-%s" % (self.a, self.b)

admin.py

class ThroughInline(admin.TabularInline):

    model = Through

    def has_add_permission(self, request, obj):
        # setting this to False results in an error
        return False


class ModelAAdmin(admin.ModelAdmin):
    inlines = (ThroughInline, )


class ModelBAdmin(admin.ModelAdmin):
    inlines = (ThroughInline, )

class ThroughAdmin(admin.ModelAdmin):
    pass

Then create your objects.

>>> from <yourapp>.models import ModelA, ModelB, Through
>>> a = ModelA.objects.create(name='a')
>>> b= ModelB.objects.create(name='b')
>>> t = Through.objects.create(a=a, b=b)

Fire up a runserver and visit the admin api: http://localhost:8000/admin/<yourapp>/modela/1/change/

result

A server 500

KeyError at /admin/<appname>/modela/1/change/

Request Method:	GET
Request URL:	http://localhost:8000/admin/<appname>/modela/1/change/
Django Version:	2.1
Exception Type:	KeyError
Exception Value: 'b'

Template error:
In template ...contrib/admin/templates/admin/edit_inline/tabular.html, error at line 13
   b
   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>


Traceback:

File "/venv3/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/venv3/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  156.                 response = self.process_exception_by_middleware(e, request)

File "/venv3/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  154.                 response = response.render()

File "/venv3/lib/python3.5/site-packages/django/template/response.py" in render
  106.             self.content = self.rendered_content

File "/venv3/lib/python3.5/site-packages/django/template/response.py" in rendered_content
  83.         content = template.render(context, self._request)

expected result

The inlines are displayed without the option to create new Through instances.

version

Django==2.1

Change History (2)

comment:1 by Harm Verhagen, 6 years ago

Description: modified (diff)

comment:2 by Harm Verhagen, 6 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top