在我的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)
现在,当我创建并尝试在POST请求的视图中验证它时:
my_formset = SomeFormset(request.POST, request.FILES)
if(my_formset.is_valid()):
# FAIL
如果将额外呈现的表单提交为空,则始终无法通过上述检查。
如果我在最后一个空的额外表单上检查form.changed_data
,我会得到有选项的字段(如上面的 pickme )。
换句话说,当需要一些选择字段时,formset不够聪明,无法确定应该忽略空提交的表单。
答案 0 :(得分: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)
我们这样做:
pickme = forms.ChoiceField(choices=choices, initial=A)
然后当一个formset检查额外的表单时,它会看到pickme的初始值为A,现在它也是A,并且会认为它没有变化。
答案 1 :(得分:10)
这不是formset的常见行为。 Formsets pass empty_permitted=True to all "extra" forms和a form with empty_permitted that hasn't been modified should always pass validation。请注意,这在Django管理员中运行得很好(如果使用内联)。
您必须在代码中执行其他操作,否则会破坏此行为。发布相关表格的完整代码?