Django FormWizard动态生成FormSet无法触发done()方法问题
问题分析与解决
你的核心问题出在get_form方法处理步骤1的逻辑上:每次进入步骤1时,你都直接用initial创建新的FormSet,完全忽略了用户提交的表单数据。这会导致FormSet永远不会验证用户的输入,Django Form Wizard会认为当前步骤的表单无效,因此停留在步骤1,无法进入done方法。
修正后的视图代码
class MenuAddWizard(LoginRequiredMixin, SessionWizardView): form_list = [MenuInputForm, DayMenuFormSet] template_name = "menu_add.html" def get_form(self, step=None, data=None, files=None): if step is None: step = self.steps.current if step == '1': # 获取步骤0的清理数据(用于生成动态初始值) step_0_data = self.get_cleaned_data_for_step('0') # 基于步骤0数据计算需要的初始值(这里用示例数据代替你的业务逻辑) initial_data = [ {'menu': 'Some example menu'}, {'menu': 'This is some other example text'} ] # 关键:如果有提交数据,用data初始化FormSet;否则用initial DayMenuFormSet = formset_factory(form=DayMenuForm, min_num=1, extra=0) if data: form = DayMenuFormSet(data=data) else: form = DayMenuFormSet(initial=initial_data) return form # 其他步骤调用父类方法 return super().get_form(step, data, files) def done(self, form_list, **kwargs): # 现在可以正常进入这里了 # 处理表单数据,比如: step0_data = form_list[0].cleaned_data step1_forms = form_list[1].cleaned_data # 后续逻辑... return redirect('some-success-url')
额外优化点
- 模板结构调整:你的模板里重复输出了
{{ wizard.management_form }},虽然不影响功能,但可以调整为更清晰的结构:
<form action="" method="post">{% csrf_token %} <table> {{ wizard.management_form }} <!-- Wizard的步骤管理表单,必须保留 --> {% if wizard.form.forms %} {{ wizard.form.management_form }} <!-- FormSet的管理表单,必须保留 --> {% for form in wizard.form.forms %} {{ form.as_table }} {% endfor %} {% else %} {{ wizard.form }} {% endif %} </table> <input type="submit" value="Submit"/> </form>
- 统一FormSet参数:你可以把
DayMenuFormSet的定义移到视图外,或者在get_form中确保每次生成的FormSet参数(如min_num、extra)和form_list中的一致,避免验证时出现不匹配。
内容的提问来源于stack exchange,提问作者SaeX
相关产品推荐
相关产品推荐

