我正在尝试创建一个Django表单向导,以便我的用户可以输入模型 批量实例进入数据库。对于这个特定的型号, 其中几个字段是ManyToMany字段,其中包含相关的长列表 楷模。用户几乎总是添加10多个共享许多实例 最繁琐的输入字段的值。
所以我的向导有两种形式:第一种是查询的手动表单 用户在第二步中用于所有表格的公共值,即a ModelFormSet。应删除第一个表单中设置的字段 每个表格在第二个,以尽量减少用户的恐怖。所以我需要创建 第二步中的ModelFormSet基于第一步中输入的值。
我首先使用Django 1.7。
最明显的解决方案是覆盖向导的get_form 方法,如果我们在第二步中,使用第一步中的值 构建一个新的modelformset:
def get_form(self, step=None, data=None, files=None):
"""In the second step, the WorkSet form needs to be dynamically created."""
form = super(WorkBulkWizard, self).get_form(step, data, files)
if step is None:
step = self.steps.current
if step == "1":
d = self.get_cleaned_data_for_step("0")
fields = ["title"]
# use values from "d" to add fields to "fields"
NewFormSet = modelformset_factory(Work, fields=tuple(fields), can_delete=False, extra=10)
form = NewFormSet(queryset=Work.objects.none())
return form
这会生成正确的formset,但是当我提交表单时,我会返回到 同一表单提交页面的空白版本。没有处理,没有 重定向,并没有触及向导的完成方法。我不知道 为什么。如果我删除了get_form方法的这个重载,并让 向导显示一个标准的ModelFormSet,然后提交工作为 正常。但是,由于ModelFormSet是一个可怕的目标,这就失败了 九屏数据录入盛会。
This solution, 使用Django 1.4,建议覆盖向导的get_context_data 将表单注入模板而不是表单的方法 在向导构造函数中指定。那个答案使用了一个虚拟形式(一个 empty forms.Form subclass)作为占位符,然后以相同的方式替换它 如上所述,只是采用不同的方法:
def get_context_data(self, form, **kwargs):
context = super(WorkBulkWizard, self).get_context_data(form=form, **kwargs)
if self.steps.current == "1":
d = self.get_cleaned_data_for_step("0")
fields = ["title"]
# Do the same manipulation of "fields" as above
NewFormSet = modelformset_factory(Work, fields=tuple(fields), can_delete=False, extra=10)
form = NewFormSet(queryset=Work.objects.none())
context = super(WorkBulkWizard, self).get_context_data(form=form, **kwargs)
return context
但是自1.4版以来必须有所改变,因为Django 仍然认为我在第二步中使用了虚拟表格,而且 在该步骤中输入的数据不在form_list参数中 完成方法。
我考虑使用会话数据手动执行此操作,但是 看起来像是一个向导的正确应用......有什么建议吗?