SessionWizardView 状态仅保存在最终表单中,done() 未执行
Posted
技术标签:
【中文标题】SessionWizardView 状态仅保存在最终表单中,done() 未执行【英文标题】:SessionWizardView state only saved on final form, done() not executed 【发布时间】:2016-02-10 22:03:45 【问题描述】:我有几个表单已添加到向导中,但表单状态仅在最后一步保持,并且不执行 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]]
this 用于模板(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 步并输入数据,然后返回第 1 步,第一步没有保存数据,也没有显示表单错误。当我点击下一步返回第 2 步时,第 2 步的数据仍然存在。故意将无效数据放在第 1 步向我表明它也不会验证表单,因为向导会继续执行第 2 步而不显示错误。
当我提交表单时,done() 不会执行。如果只有最后一步实际成功,这是有道理的,但在第 1 步中没有看到任何错误让我感到困惑。
为什么除了最终表单之外没有维护表单数据?为什么最后一步是唯一真正验证表单数据的步骤?为什么没有执行?
更新:看来表单验证毕竟正在进行,我确实通过在 post 函数中打印相关信息看到它成功,但 done() 似乎仍然没有被执行。
谢谢。
【问题讨论】:
【参考方案1】:找到here 的文档中的第 1 步就是答案。它陈述了以下内容。
用户访问向导的第一页,填写表格并提交。
这里的关键是“提交”。除非提交表单,否则不会保存表单验证或状态。使用 Wizard_goto_step 进行下一个/上一个/跳转不会提交表单,不会验证表单,也不会将表单保存在会话/cookie 中(取决于您选择的)。
现在很明显,但我仍然认为这会误导表单向导的潜在最终用户。在进入下一步时,我可以很容易地将wizard_goto_step 替换为实际提交,但是当用户在表单中输入一些数据,然后选择重新访问另一个步骤时,他们在该步骤中的所有数据都会丢失。
感觉表单数据即使不完整也应该保存。我的意图是使用 storage.set_step_data() 函数手动保存这些数据,因为无论如何在最终处理时都会重新验证所有表单步骤。即使用户在步骤中填写了不正确的数据,他们仍然会被重定向到最后缺少数据的步骤。这感觉比在用户访问上一步时盲目地擦除用户数据更好的行为。
【讨论】:
嗨,威尔贝!我面临同样的问题,即 done() 没有被执行,并且 ui 在最后一步之后跳转到第一步没有任何错误。作为 django 的新手,如果可能的话,请你给我一个例子。这是我的 SO 帖子***.com/questions/56635382/… @subbu,我已经有一段时间没有使用表单向导做很多事情了,但我记得的应该包含在我下面写的内容中。底线......表单向导并不像它应该的那样自然直观。仔细阅读它是如何为我“解决”的事情的。我想你可能和我在一条类似的船上,你认为它应该做的事情是不准确的。我最近没看过,但我敢打赌有一个更好的替代 3rd 方表单系统,它更能保持状态并在表单的不同步骤之间跳转。【参考方案2】:这当然是一个错误。您必须从
中删除以下代码行\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 例程的原因。
【讨论】:
以上是关于SessionWizardView 状态仅保存在最终表单中,done() 未执行的主要内容,如果未能解决你的问题,请参考以下文章
Django SessionWizardView 页面重新加载后跳回第一步