You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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')

额外优化点

  1. 模板结构调整:你的模板里重复输出了{{ 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>
  1. 统一FormSet参数:你可以把DayMenuFormSet的定义移到视图外,或者在get_form中确保每次生成的FormSet参数(如min_num、extra)和form_list中的一致,避免验证时出现不匹配。

内容的提问来源于stack exchange,提问作者SaeX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:30:13