Updated: I now think this is an existing bug in Django reported as Ticket 14642
This has been driving me crazy and I thought it was due to my Form code but I realize now I can recreate it using my models and the admin. I would like to know what the expected behavior here is:
models.py:
class Thingy(models.Model):
description = models.CharField(max_length=256)
class ThingyItem(models.Model):
thingy = models.ForeignKey(Thingy)
description = models.CharField(max_length=256)
admin.py:
class ThingyItemInline(admin.TabularInline):
model = ThingyItem
extra = 0
class ThingyAdmin(admin.ModelAdmin):
inlines = [ThingyItemInline,]
admin.site.register(Thingy, ThingyAdmin)
admin.site.register(ThingyItem)
Now do the following:
When I do this, I get:
Traceback:
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/core/handlers/base.py" in get_response
100. response = callback(request, *callback_args, **callback_kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/contrib/admin/options.py" in wrapper
265. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
76. response = view_func(request, *args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
78. response = view_func(request, *args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/contrib/admin/sites.py" in inner
190. return view(request, *args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapper
21. return decorator(bound_func)(*args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/utils/decorators.py" in _wrapped_view
76. response = view_func(request, *args, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/utils/decorators.py" in bound_func
17. return func(self, *args2, **kwargs2)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/db/transaction.py" in _commit_on_success
299. res = func(*args, **kw)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/contrib/admin/options.py" in change_view
916. queryset=inline.queryset(request))
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/models.py" in __init__
701. queryset=qs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/models.py" in __init__
427. super(BaseModelFormSet, self).__init__(**defaults)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/formsets.py" in __init__
47. self._construct_forms()
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/formsets.py" in _construct_forms
98. self.forms.append(self._construct_form(i))
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/models.py" in _construct_form
714. form = super(BaseInlineFormSet, self)._construct_form(i, **kwargs)
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/forms/models.py" in _construct_form
451. kwargs['instance'] = self.get_queryset()[i]
File "/Users/poswald/.virtualenvs/hats/lib/python2.6/site-packages/django/db/models/query.py" in __getitem__
171. return self._result_cache[k]
Exception Type: IndexError at /admin/exampletest/thingy/1/
Exception Value: list index out of range
I wouldn't really care about this in the admin except it's happening on our production server in code using my own forms. It seems that the inline formset code is quite brittle. It trusts the data sent in with the management form when really it should check that those assumptions are still valid.
Now, I think this is worth reporting in the Django Trac - and I plan to do that right now - however I was wondering if anyone here has ever had this happen and if so, how did you work around it? Is there an easy way to test if these preconditions assumed by the form are still valid? Am I expected to do that in my view or form code?
For anyone else hitting this, it seems to be a bug in Django. I've opened an issue to tack it here: http://code.djangoproject.com/ticket/15574