#15665: Inline admins are broken when primary key is not an AutoField and not
editable.
------------------------------------------+---------------------------
 Reporter:  sebastian_noack               |         Owner:  nobody
   Status:  new                           |     Milestone:
Component:  Database layer (models, ORM)  |       Version:  1.2
 Keywords:                                |  Triage Stage:  Unreviewed
Has patch:  0                             |
------------------------------------------+---------------------------
 For each inline object, a hidden field for its primary key (if it is an
 AutoField) is included in the form. But if you inherit from a concrete
 model that has a custom (not AutoField) primary key, you end up in a
 situation where you have a primary key which is a OneToOneField that is
 not editable in the admin.

 {{{
 #!python
 from django.db import models

 class Event(models.Model):
     name = models.CharField(max_length=100, primary_key=True)

     def __unicode__(self):
         return self.name

 class Person(models.Model):
     name = models.CharField(max_length=100, primary_key=True)

     def __unicode__(self):
         return self.name

 class Visitor(Person):
     event = models.ForeignKey(Event)

     def __unicode__(self):
         return u"'%s' at '%s'" % (self.person_ptr, self.event)
 }}}

 {{{
 #!python
 from django.contrib import admin

 class VisitorInline(admin.StackedInline):
     model = Visitor

 class EventAdmin(admin.ModelAdmin):
     inlines = [VisitorInline]

 admin.site.register(Event, EventAdmin)
 }}}

 In that case there is no element in the form that holds the primary key
 and you get the Exception below, when you try to save an existing object
 in the admin.

 {{{
 Traceback (most recent call last):

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/servers/basehttp.py",
 line 280, in run
     self.result = application(self.environ, self.start_response)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/servers/basehttp.py",
 line 674, in __call__
     return self.application(environ, start_response)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/handlers/wsgi.py",
 line 241, in __call__
     response = self.get_response(request)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/handlers/base.py",
 line 141, in get_response
     return self.handle_uncaught_exception(request, resolver,
 sys.exc_info())

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/handlers/base.py",
 line 165, in handle_uncaught_exception
     return debug.technical_500_response(request, *exc_info)

   File "/home/sebastian/djacap/fam/src/famtest/django/views/debug.py",
 line 58, in technical_500_response
     html = reporter.get_traceback_html()

   File
 "/home/sebastian/djacap/fam/src/famtest/django/core/handlers/base.py",
 line 100, in get_response
     response = callback(request, *callback_args, **callback_kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/contrib/admin/options.py",
 line 239, in wrapper
     return self.admin_site.admin_view(view)(*args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/utils/decorators.py", line
 76, in _wrapped_view
     response = view_func(request, *args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/views/decorators/cache.py",
 line 69, in _wrapped_view_func
     response = view_func(request, *args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/contrib/admin/sites.py",
 line 190, in inner
     return view(request, *args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/utils/decorators.py", line
 21, in _wrapper
     return decorator(bound_func)(*args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/utils/decorators.py", line
 76, in _wrapped_view
     response = view_func(request, *args, **kwargs)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/utils/decorators.py", line
 17, in bound_func
     return func(self, *args2, **kwargs2)

   File "/home/sebastian/djacap/fam/src/famtest/django/db/transaction.py",
 line 299, in _commit_on_success
     res = func(*args, **kw)

   File
 "/home/sebastian/djacap/fam/src/famtest/django/contrib/admin/options.py",
 line 890, in change_view
     queryset=inline.queryset(request))

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/models.py",
 line 705, in __init__
     queryset=qs)

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/models.py",
 line 429, in __init__
     super(BaseModelFormSet, self).__init__(**defaults)

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/formsets.py",
 line 47, in __init__
     self._construct_forms()

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/formsets.py",
 line 97, in _construct_forms
     self.forms.append(self._construct_form(i))

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/models.py",
 line 718, in _construct_form
     form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)

   File "/home/sebastian/djacap/fam/src/famtest/django/forms/models.py",
 line 446, in _construct_form
     pk = self.data[pk_key]

   File
 "/home/sebastian/djacap/fam/src/famtest/django/utils/datastructures.py",
 line 235, in __getitem__
     raise MultiValueDictKeyError("Key %r not found in %r" % (key, self))

 MultiValueDictKeyError: "Key 'visitor_set-0-person_ptr' not found in
 <QueryDict: {u'visitor_set-__prefix__-event': [u'FOSDEM'], u'name':
 [u'FOSDEM'], u'visitor_set-0-name': [u'Me'], u'visitor_set-3-event':
 [u'FOSDEM'], u'visitor_set-3-name': [u''], u'visitor_set-1-event':
 [u'FOSDEM'], u'visitor_set-1-name': [u''], u'visitor_set-2-event':
 [u'FOSDEM'], u'visitor_set-2-name': [u''], u'visitor_set-INITIAL_FORMS':
 [u'1'], u'visitor_set-TOTAL_FORMS': [u'4'], u'csrfmiddlewaretoken':
 [u'85dd78ff278138c4c70f2d1c8107bd95'], u'visitor_set-0-event':
 [u'FOSDEM'], u'_continue': [u'Save and continue editing'], u'visitor_set-
 MAX_NUM_FORMS': [u''], u'visitor_set-__prefix__-name': [u'']}>"
 }}}

 I found following line in ''admin/edit_inline/tabular.html'' and
 ''admin/edit_inline/stacked.html''.

 {{{
 {% if inline_admin_form.has_auto_field %}{{
 inline_admin_form.pk_field.field }}{% endif %}
 }}}

 Removing the check for ''has_auto_field'' fixed the error described above,
 but leads to wrong behavior, when modifying the value of the concrete base
 class's primary key (the ''name'' field in the example above) in the
 inline admin, resulting in a new entry.

 I have reproduced that issue with django 1.2.3, 1.2.4, 1.2.5 and the
 latest version from SVN.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/15665>
Django <http://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 post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to