Django Formset.is_valid()没有额外的表单

And*_*yuk 15 django django-forms formset

在我的Django应用程序应用程序中,我有一个从简单(非模型)形式创建的formset,其中extra = 1(以允许javasript稍后添加更多表单).

class SomeForm(forms.Form):
    #some fields with required=False
    length = forms.IntegerField(required=False)

    # An example of one of the fields with choices i have
    A = 0
    B = 1
    C = 2
    D = 3

    choices = ((A, 'Aah'), (B, 'Baa'), (C, 'Caa'), (D, 'Daa'))

    # This is a required choice field
    pickme = forms.ChoiceField(choices=choices)


SomeFormset = formset_factory(SomeForm, can_delete=True, extra=1)
Run Code Online (Sandbox Code Playgroud)

现在,当我创建并尝试在我的POST请求视图中验证它时:

my_formset = SomeFormset(request.POST, request.FILES)

if(my_formset.is_valid()):
    # FAIL
Run Code Online (Sandbox Code Playgroud)

如果额外呈现的表单被提交为空,则它始终未通过上述检查.

如果我检查form.changed_data最后一个空的额外表格,我会得到有选择的字段(如上面的pickme).换句话说,当需要某些选项字段时,formset不够聪明,无法确定应忽略空提交的表单.

And*_*yuk 22

谢谢卡尔,你让我发现了问题的根源.

在创建带有选择字段的表单时,我们必须设置初始值,否则表单会认为该字段已更改.

所以对于这样的表格:

class SomeForm(forms.Form):

    A = 0
    B = 1
    C = 2
    D = 3

   choices = ((A, 'Aah'), (B, 'Baa'), (C, 'Caa'), (D, 'Daa'))

    # This is a required choice field
    pickme = forms.ChoiceField(choices=choices)
Run Code Online (Sandbox Code Playgroud)

我们这样做:

pickme = forms.ChoiceField(choices=choices, initial=A)
Run Code Online (Sandbox Code Playgroud)

然后当一个formset检查额外的表单时,它会看到pickme的初始值为A,现在它也是A,并且会认为它没有变化.


Car*_*yer 10

这不是formsets的通常行为. Formsets将empty_permitted = True传递给所有"额外"表单,而具有empty_permitted但尚未修改的表单应始终通过验证.请注意,这在Django管理员中运行得很好(如果使用内联).

您必须在代码中执行其他操作,否则会在某处破坏此行为.发布相关表格的完整代码?