SessionWizardView 状态仅保存在最终表单中,done() 未执行

SessionWizardView state only saved on final form, done() not executed

我有几个表单已添加到向导中,但表单状态仅在最后一步保持,并且未执行 done()。

我创建了以下内容,主要基于 django 文档中的示例,以尝试深入了解这一点。似乎最后一步是唯一在步骤之间移动时保存状态的步骤。

class OneForm( Form ):
    field_one = forms.CharField(label='1', max_length=100)
    field_two = forms.CharField(label='2', max_length=100)
    field_three = forms.CharField(label='3', max_length=100)
class TwoForm( Form ):
    field_one = forms.CharField(label='4', max_length=100)
    field_two = forms.CharField(label='5', max_length=100)
    field_three = forms.CharField(label='6', max_length=100)

TEST_WIZARD_FORMS = [
    ("one", OneForm),
    ("two", TwoForm),
]
TEST_TEMPLATES = {
    'one': 'tour/one.html',
    'two': 'tour/two.html',
}
class TestWizardView( SessionWizardView ):
    form_list = TEST_WIZARD_FORMS
    def done(self, form_list, **kwargs):
        print('done executed')
        return reverse('home')
    def get_template_names(self):
        return [TEST_TEMPLATES[self.steps.current]]

这是模板(one.html 和 two.html 是相同的)

<html>
<body>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
    {{ wizard.form.management_form }}
    {{ wizard.form.non_field_errors }}
    {{ wizard.form.errors }}
    {% for form in wizard.form.forms %}
        {{ form }}
    {% endfor %}
{% else %}
    {{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button>
{% endif %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.next }}">"next step"</button>
<input type="submit" value="submit"/>
</form>
</body>
</html>

如果我在第 1 步输入数据,继续第 2 步输入数据,然后 return 到第 1 步,第一步没有保存数据,也没有显示表单错误。当我点击 return 旁边的第 2 步时,第 2 步的数据仍然存在。故意在步骤 1 中放置无效数据表明它也不验证表单,因为向导会继续执行步骤 2 而不会显示错误。

当我提交表单时,done() 没有执行。如果只有最后一步真正成功,这是有道理的,但看到第 1 步没有错误让我感到困惑。

为什么表单数据除了在最终表单上没有维护?为什么最后一步是唯一真正验证表单数据的步骤?为什么done不执行?

更新: 看来表单验证毕竟发生了,我确实通过在 post 函数中打印相关信息看到它成功了,但 done() 仍然似乎没有被执行。

谢谢。

找到的文档中的第 1 步 here 就是答案。它说明如下。

The user visits the first page of the wizard, fills in the form and submits it.

此处的关键是 "submit." 除非提交表单,否则不会保存表单验证或状态。将 wizard_goto_step 用于 next/previous/jump 不会提交表单,不会验证表单,并且不会将表单保存在 session/cookie 中(取决于您选择的)。

现在很明显,但我仍然认为这会误导表单向导的潜在最终用户。在进入下一步时,用实际提交替换 wizard_goto_step 对我来说很容易,但是当用户在表单中输入一些数据,然后选择重新访问另一个步骤时,他们在该步骤上的所有数据丢失了。

感觉表单数据不完整也应该保存。我的意图是使用 storage.set_step_data() 函数手动保存此数据,因为所有表单步骤在最终处理时都是 re-validated。即使用户在某个步骤中填写了错误的数据,他们仍将被重定向到最后缺少数据的步骤。这感觉比在用户访问上一步时盲目擦除用户数据更好。

这肯定是一个错误。您必须从

中删除以下代码行

\formtools\wizard\views.py

        # walk through the form list and try to validate the data again.
#         for form_key in self.get_form_list():
#             form_obj = self.get_form(step=form_key,
#                 data=self.storage.get_step_data(form_key),
#                 files=self.storage.get_step_files(form_key))
#             if not form_obj.is_valid():
#                 return self.render_revalidation_failure(form_key,
#                                                         form_obj,
#                                                         **kwargs)
#             final_forms[form_key] = form_obj

其实我不明白这段代码的原因。每个表单在提交后都经过验证。我认为没有理由再次验证它们?

此验证由于某些未知原因而失败,这就是为什么以后从未调用 done 例程的原因。