开发者

Django inline formset throws IndexError when users are concurrently editing

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:

  • Create a new Thingy with several ThingyItems in the admin and save it.
  • Open the edit page.
  • Open the edit page for the same thingy in a second browser window.
  • Check the "Delete" button on the last ThingyItem and save it in the second window.
  • Now go back to the first form and save it

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 o开发者_JS百科r 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜