Opened 14 years ago

Closed 14 years ago

Last modified 14 years ago

#14065 closed (duplicate)

Admin: non-AutoField primary_key in child model breaks admin inlines (MultiValueDictKeyError)

Reported by: Marti Raudsepp Owned by: nobody
Component: Contrib apps Version: 1.2
Severity: 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

Let's say I have a parent-child model, where the child model has an explicit primary_key=True field. The parent admin page contains an inline for editing the child. Saving, or deleting the child, fails with a "MultiValueDictKeyError", because the primary key of the child is not being submitted. Full model&admin included below.

Environment:

Request Method: POST
Request URL: http://localhost:8001/admin/myapp/parent/1/
Django Version: 1.2.1
Python Version: 2.6.5
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.admin',
 'wtf.myapp']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')

Exception Type: MultiValueDictKeyError at /admin/myapp/parent/1/
Exception Value: "Key 'child_set-0-child_id' not found in
  <QueryDict: {u'child_set-0-name': [u'bar'], u'child_set-3-name': [u''], u'child_set-3-parent': [u'1'],
    u'child_set-MAX_NUM_FORMS': [u''], u'name': [u'foo'], u'_save': [u'Save'], u'child_set-__prefix__-name': [u''],
    u'child_set-__prefix__-parent': [u'1'], u'child_set-2-parent': [u'1'], u'child_set-2-name': [u''],
    u'child_set-0-parent': [u'1'], u'child_set-TOTAL_FORMS': [u'4'], u'child_set-1-parent': [u'1'],
    u'csrfmiddlewaretoken': [u'055944541276fbcb6a8a6d2fcb54968a'], u'child_set-INITIAL_FORMS': [u'1'],
    u'child_set-1-name': [u'']}>"

Traceback:
File "/usr/lib/python2.6/site-packages/django/core/handlers/base.py" in get_response
  100.                     response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.6/site-packages/django/contrib/admin/options.py" in wrapper
  239.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
  76.                     response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  69.         response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/contrib/admin/sites.py" in inner
  190.             return view(request, *args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapper
  21.             return decorator(bound_func)(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
  76.                     response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.6/site-packages/django/utils/decorators.py" in bound_func
  17.                 return func(self, *args2, **kwargs2)
File "/usr/lib/python2.6/site-packages/django/db/transaction.py" in _commit_on_success
  299.                     res = func(*args, **kw)
File "/usr/lib/python2.6/site-packages/django/contrib/admin/options.py" in change_view
  890.                                   queryset=inline.queryset(request))
File "/usr/lib/python2.6/site-packages/django/forms/models.py" in __init__
  698.                                                 queryset=qs)
File "/usr/lib/python2.6/site-packages/django/forms/models.py" in __init__
  423.         super(BaseModelFormSet, self).__init__(**defaults)
File "/usr/lib/python2.6/site-packages/django/forms/formsets.py" in __init__
  47.         self._construct_forms()
File "/usr/lib/python2.6/site-packages/django/forms/formsets.py" in _construct_forms
  97.             self.forms.append(self._construct_form(i))
File "/usr/lib/python2.6/site-packages/django/forms/models.py" in _construct_form
  711.         form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
File "/usr/lib/python2.6/site-packages/django/forms/models.py" in _construct_form
  439.             pk = self.data[pk_key]
File "/usr/lib/python2.6/site-packages/django/utils/datastructures.py" in __getitem__
  233.             raise MultiValueDictKeyError("Key %r not found in %r" % (key, self))

model.py

from django.db import models

class Parent(models.Model):
    name = models.CharField(max_length=128)

class Child(models.Model):
    child_id = models.IntegerField(primary_key=True)
    # this also fails: id = models.IntegerField(primary_key=True, db_column='child_id')
    name = models.CharField(max_length=128)
    parent = models.ForeignKey(Parent)

admin.py

from wtf.myapp.models import *
from django.contrib import admin

class ChildInline(admin.TabularInline):
  model = Child
  fields = ['parent', 'name']

class ParentAdmin(admin.ModelAdmin):
  inlines = [ChildInline]
  fields = ['name']
admin.site.register(Parent, ParentAdmin)

Reproducing

  1. Create project and app, enable admin, add the above files and syncdb.
  2. Go to the admin interface and create a new Parent object
  3. Add a new child object to the parent
  4. Save
  5. Go back the the list
  6. Open the same parent object again
  7. Click save. Bam!

Change History (2)

comment:1 by Ramiro Morales, 14 years ago

Resolution: duplicate
Status: newclosed

Seems like a duplicate of #12599. You are using a fields option in you Child Inline that excludes your IntegerField (and as such, manually controllable) PK, this is similar to the case attached to that ticker where the reporter was excluding his IntegerField PK by using the exclude option.

comment:2 by Marti Raudsepp, 14 years ago

Summary: Admin: Explicit primary_key in child model breaks admin inlines (MultiValueDictKeyError)Admin: non-AutoField primary_key in child model breaks admin inlines (MultiValueDictKeyError)

You're right, AutoField is the solution. But since I'm not the first one to trip on this problem, I think you need a better error message here. I spent many hours trying to figure out what was wrong (I was using inspectdb to create the model and it doesn't recognize AutoField/serial columns in Postgres)

Note: See TracTickets for help on using tickets.
Back to Top