Code

Opened 4 years ago

Closed 4 years ago

Last modified 3 years ago

#12700 closed (fixed)

readonly_fields specified on inline model admin cause KeyError since r12297

Reported by: kmtracey Owned by: nobody
Component: Uncategorized Version: master
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation:
Needs tests: Patch needs improvement:
Easy pickings: UI/UX:

Description

Given these models:

class Puzzle(models.Model):
    title = models.CharField(max_length=240)

class Clue(models.Model):
    puzzle = models.ForeignKey(Puzzle)
    text = models.CharField(max_length=240)
    num = models.IntegerField()

and these admin defs:

from ttt.models import Puzzle, Clue

class ClueInline(admin.TabularInline):
    model = Clue
    readonly_fields = ('num',)

class PuzzleAdmin(admin.ModelAdmin):
    inlines = [ClueInline]

admin.site.register(Puzzle, PuzzleAdmin)

an attempt to bring up and add or change page for a Puzzle will result in:

Environment:

Request Method: GET
Request URL: http://localhost:6666/admin/ttt/puzzle/add/
Django Version: 1.2 alpha 1 SVN-12297
Python Version: 2.5.2
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'ttt',
 'debug_toolbar']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.transaction.TransactionMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware')

Template error:
In template /home/kmt/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html, error at line 33
   Caught an exception while rendering: "Key 'num' not found in Form"
   23 :         <tr class="{% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
   24 :              id="{{ inline_admin_formset.formset.prefix }}{% if not forloop.last %}{{ forloop.counter }}{% else %}-empty{% endif %}">
   25 :         <td class="original">
   26 :           {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
   27 :           {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
   28 :           {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
   29 :             </p>{% endif %}
   30 :           {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
   31 :           {{ inline_admin_form.fk_field.field }}
   32 :           {% spaceless %}
   33 :            {% for fieldset in inline_admin_form %} 
   34 :             {% for line in fieldset %}
   35 :               {% for field in line %}
   36 :                 {% if field.is_hidden %} {{ field.field }} {% endif %}
   37 :               {% endfor %}
   38 :             {% endfor %}
   39 :           {% endfor %}
   40 :           {% endspaceless %}
   41 :         </td>
   42 :         {% for fieldset in inline_admin_form %}
   43 :           {% for line in fieldset %}

Traceback:
File "/home/kmt/django/trunk/django/core/handlers/base.py" in get_response
  101.                     response = callback(request, *callback_args, **callback_kwargs)
File "/home/kmt/django/trunk/django/contrib/admin/options.py" in wrapper
  238.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/kmt/django/trunk/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/kmt/django/trunk/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/kmt/django/trunk/django/utils/decorators.py" in __call__
  36.         return self.decorator(self.func)(*args, **kwargs)
File "/home/kmt/django/trunk/django/views/decorators/cache.py" in _wrapped_view_func
  70.         response = view_func(request, *args, **kwargs)
File "/home/kmt/django/trunk/django/contrib/admin/sites.py" in inner
  190.             return view(request, *args, **kwargs)
File "/home/kmt/django/trunk/django/utils/decorators.py" in _wrapped_view
  86.                     response = view_func(request, *args, **kwargs)
File "/home/kmt/django/trunk/django/db/transaction.py" in _commit_on_success
  295.                     res = func(*args, **kw)
File "/home/kmt/django/trunk/django/contrib/admin/options.py" in add_view
  839.         return self.render_change_form(request, context, form_url=form_url, add=True)
File "/home/kmt/django/trunk/django/contrib/admin/options.py" in render_change_form
  631.         ], context, context_instance=context_instance)
File "/home/kmt/django/trunk/django/shortcuts/__init__.py" in render_to_response
  20.     return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "/home/kmt/django/trunk/django/template/loader.py" in render_to_string
  173.     return t.render(context_instance)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  184.             return self._render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in _render
  178.         return self.nodelist.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  72.             result = node.render(context)
File "/home/kmt/django/trunk/django/template/loader_tags.py" in render
  128.         return compiled_parent._render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in _render
  178.         return self.nodelist.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  72.             result = node.render(context)
File "/home/kmt/django/trunk/django/template/loader_tags.py" in render
  128.         return compiled_parent._render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in _render
  178.         return self.nodelist.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  72.             result = node.render(context)
File "/home/kmt/django/trunk/django/template/loader_tags.py" in render
  62.             result = block.nodelist.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  72.             result = node.render(context)
File "/home/kmt/django/trunk/django/template/defaulttags.py" in render
  176.                 nodelist.append(node.render(context))
File "/home/kmt/django/trunk/django/template/loader_tags.py" in render
  154.             return t.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  184.             return self._render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in _render
  178.         return self.nodelist.render(context)
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  72.             result = node.render(context)
File "/home/kmt/django/trunk/django/template/defaulttags.py" in render
  176.                 nodelist.append(node.render(context))
File "/home/kmt/django/trunk/django/template/defaulttags.py" in render
  334.         return strip_spaces_between_tags(self.nodelist.render(context).strip())
File "/home/kmt/django/trunk/django/template/__init__.py" in render
  787.                 bits.append(self.render_node(node, context))
File "/home/kmt/django/trunk/django/template/debug.py" in render_node
  82.             raise wrapped

Exception Type: TemplateSyntaxError at /admin/ttt/puzzle/add/
Exception Value: Caught an exception while rendering: "Key 'num' not found in Form"

Original Traceback (most recent call last):
  File "/home/kmt/django/trunk/django/template/debug.py", line 72, in render_node
    result = node.render(context)
  File "/home/kmt/django/trunk/django/template/defaulttags.py", line 176, in render
    nodelist.append(node.render(context))
  File "/home/kmt/django/trunk/django/template/defaulttags.py", line 176, in render
    nodelist.append(node.render(context))
  File "/home/kmt/django/trunk/django/template/defaulttags.py", line 146, in render
    values = list(values)
  File "/home/kmt/django/trunk/django/contrib/admin/helpers.py", line 102, in __iter__
    yield AdminField(self.form, field, is_first=(i == 0))
  File "/home/kmt/django/trunk/django/contrib/admin/helpers.py", line 109, in __init__
    self.field = form[field] # A django.forms.BoundField instance
  File "/home/kmt/django/trunk/django/forms/forms.py", line 105, in __getitem__
    raise KeyError('Key %r not found in Form' % name)
KeyError: "Key 'num' not found in Form"

If I back off to r12296 the exception goes away, though there was something slightly wrong in the previous version also -- (None) is displayed for the values of num in the extra lines where new Clues could be entered. Not sure what should be shown, but probably not (None)

Attachments (0)

Change History (2)

comment:1 Changed 4 years ago by jezdez

  • Resolution set to fixed
  • Status changed from new to closed

(In [12368]) Fixed #12700 - Take read-only fields into account when rendering the empty form for dynamic inlines.

comment:2 Changed 3 years ago by jacob

  • milestone 1.2 deleted

Milestone 1.2 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.