我有一个显示多个Formset的页面,每个Formset都有一个前缀。使用formset_factory
默认选项创建表单集,包括extra=1
。可以使用JavaScript添加或删除行。
如果用户正在添加新数据,则会显示一个空白行。完美。
如果用户添加了数据但表单验证失败,在这种情况下,使用MyFormset(data, prefix='o1-formsetname')
等填充POST数据的表单集,只显示他们输入的数据。再次,完美。 (o1
等是动态生成的,每个o
对应一个“选项”,每个“选项”可能有多个表单集。
但是,如果用户正在编辑现有数据,则在该情况下,视图使用MyFormset(initial=somedata, prefix='o1-formsetname')
填充表单集,其中somedata
是来自数据库中模型的数据序列的列表,在此数据之后插入空白行。除非用户使用JavaScript明确添加一行,否则我不希望显示空行。
如果设置了初始数据,是否有任何简单的方法可以阻止formset显示额外的行?我在第三个例子中使用initial
的原因是,如果我只是使用MyFormset(somedata, prefix='o1-formsetname')
传递数据,我必须做一个额外的步骤,将所有数据重新格式化为POSTdata样式的dict,包括每个字段的前缀,例如o1-formsetname-1-price: x
等,以及计算管理表单数据,这会增加一大堆复杂性。
一种解决方案可能是在将formset发送到模板并手动删除行之前拦截它,但extra_forms
属性似乎不可写,并将extra
设置为0
没有任何区别。我也可以让JavaScript检测这种情况并删除该行。但是我不禁想到,我错过了一些明显的东西,因为我想要的行为对我来说似乎是明智的预期行为。
感谢。
答案 0 :(得分:5)
将max_num
关键字参数用于formset_factory
:
MyFormset = formset_factory([...], extra=1, max_num=1)
有关详细信息,请查看limiting the maximum number of forms。
一个障碍:大概你希望能够处理多个空白表格。这不太难;只需确保不在POST处理方使用max_num
关键字参数。
答案 1 :(得分:3)
我想出了一个适用于Django 1.1的解决方案。我创建了一个BaseFormSet
的子类,它覆盖了total_form_count
方法,这样,如果存在初始表单,则总计不包含额外的表单。或许有点破解,也许有一个我找不到的更好的解决方案,但它确实有效。
class SensibleFormset(BaseFormSet):
def total_form_count(self):
"""Returns the total number of forms in this FormSet."""
if self.data or self.files:
return self.management_form.cleaned_data[TOTAL_FORM_COUNT]
else:
if self.initial_form_count() > 0:
total_forms = self.initial_form_count()
else:
total_forms = self.initial_form_count() + self.extra
if total_forms > self.max_num > 0:
total_forms = self.max_num
return total_forms