django inlineformset抛出IndexError:列表索引超出保存范围

时间:2014-02-22 20:55:02

标签: python django django-forms django-class-based-views inline-formset

所以这个人杀了我一天,我仍然不知道为什么我的解决方案有效。我想我会分享它以防有人遇到这个。
Django 1.6

我有一个FormView和一个表单和inlineformset。 我自己正在处理这个帖子

def post(self, *args, **kwargs):
    foo_form = self.form_class(self.request.POST)    
    if foo_form.is_valid():
        foo = foo_form.save(commit=False)        

        bar_formset = BarInlineFormset(self.request.POST, instance=foo)                
        if bar_formset.is_valid():
            foo.save()
            bar_formset.save()

            # redirect here
            return HttpResponseRedirect('whatever')


    kwargs['form'] = foo_form
    # in my get_context_data I'm setting context['bar_formset'] if i pass it in as a kwarg so errors from the articleformset are retained
    kwargs['bar_formset'] = bar_formset
    context = self.get_context_data(**kwargs)    

    return render(self.request, self.template_name, context)

这适用于创建全新的foo。但是一旦你尝试编辑一个foo或它的相应栏,你就会得到一个 IndexError:列表索引超出范围。
实际上错误与
完全相同 https://code.djangoproject.com/ticket/15574

然而,阅读这些错误,症状根本不同 - 即没有对象进行并发编辑,没有删除或改变关系。

发生了什么事?

1 个答案:

答案 0 :(得分:0)

浪费了一整天,包括浏览django源代码,没有做任何事情,我以为我可能会因为将实例设置为新的未保存的foo而犯了错误。

所以,如果我们正在编辑一个现有的foo,那么我只是将实例更改为实际的foo,并且所有这些都与世界再次相符。 = \

我认为实例尚未提交的事实是为什么inlineformset是barfing但我不知道为什么。也许有人可以帮助在评论中提供一些启示

def post(self, *args, **kwargs):
    try:
        foo = Foo.objects.get(id=self.kwargs['pk'])
    except KeyError:
        foo = Foo()
    foo_form = self.form_class(self.request.POST, instance=foo)            
    bar_formset = BarInlineFormset(self.request.POST, instance=foo_form.instance)                
    if foo_form.is_valid() and bar_formset.is_valid():
            foo_form.save()
            bar_formset.save()

            # redirect here
            return HttpResponseRedirect('whatever')


    kwargs['form'] = foo_form
    # in my get_context_data I'm setting context['bar_formset'] if i pass it in as a kwarg so errors from the articleformset are retained
    kwargs['bar_formset'] = bar_formset
    context = self.get_context_data(**kwargs)    

    return render(self.request, self.template_name, context)