【问题标题】:How to Dynamically Repeat Steps in Django Formwizard 1.4?如何在 Django Formwizard 1.4 中动态重复步骤?
【发布时间】:2012-10-14 16:05:50
【问题描述】:

我正在尝试根据步骤中的复选框有条件地重复 Django Formwizard (Django 1.4) 中的步骤。该表单创建了一个对象,并有一个复选框(希望如此),允许他们重复该步骤并使用相同的表单创建另一个相同模型的对象。

我看到了这个答案:Django FormWizard Dynamically Alter form_list 但不幸的是,我认为它只适用于旧版本的 FormWizard。

process_step 函数不再具有 form_list 属性。它也没有当前步骤属性(或步骤属性),但我可以通过表单的 QueryDict 访问当前步骤。它包含一个表单字典,但我认为在该字典中插入另一个步骤不会做任何事情,不幸的是,由于它是一个字典而不是一个列表,我必须在插入它之后修改每个步骤键。

那么,有没有一种使用 Django 1.4 FormWizard 向表单列表中添加新步骤的好方法?

更新——开始认为覆盖 get_next_step(self, step) 可能是要走的路,但非常感谢任何输入。

更新 #2 -- 尝试使用 get_next_step,但无法将新表单插入实例的 form_list。并不意味着不可能——想法?

【问题讨论】:

    标签: django django-1.4 formwizard


    【解决方案1】:

    嗯,我想通了。您可以覆盖 get_form_list 以将内容插入表单列表,但您必须将它们保存在 self.form_list 中,并且只返回 form_list。就我的目的而言,这没关系,但如果你也使用 conditional_dict,你必须在这里小心。

    def get_form_list(self):
        s = self.storage.current_step                                                                
        s_data = self.get_cleaned_data_for_step(s) or {}                                             
        add_another = s_data.get('add_another', False)                                   
        if add_another is True:                                                                      
            index = self.form_list.keyOrder.index(s)+1                                               
            key = "add_another-{0}".format(index)
            self.form_list.insert(index, key,                                                        
                    wizard_forms.Wizard4)                                                   
        form_list = super(Wizard, self).get_form_list()
        return form_list
    

    我可能会稍微清理一下,但这就是要点。前几行获取当前步骤并获得用于确定是否在此步骤之后插入另一个步骤的标志。如果该标志为真,我们将获取表单中当前步骤的索引,将其加一,然后在该索引处插入(在给定索引之前插入插入)。我们使用基于索引的键,这样无论该步骤重复多少次,我们都不会得到重叠的键。然后,我们将新步骤插入到 self.form_list 中,使其在实例范围内,在 self 上调用 get_form_list(它具有新的 self.form_list),并根据需要返回 form_list。

    注意事项:

    • 您必须使用 self.storage.current_step 而不是 self.steps.current,因为后者会导致无限递归。
    • 我们在初始化后使用 self.form_list 的事实意味着,如果您使用 conditional_dict,事情可能会变得有些混乱。也就是说,它们很可能不会,因为 conditional_dict 将键分配给条件,并且我们的 form_list 中的键都没有改变,只有索引。

    嗯,就是这样!显然,您需要在 done() 中添加一些逻辑来确定如何保存其中的每一个,但这取决于您正在做什么。

    【讨论】:

      【解决方案2】:

      我发布的上一个答案的工作方式非常不一致,我认为这是一些奇怪的会话冲突错误,但事实证明这是因为 get_form_list 并不总是及时调用需要表单的操作。我将相同的逻辑移到 get_next_step 中,现在它可以顺利运行。

      def get_next_step(self, step=None):
          if step is None:
              step = self.steps.current
          s_data = self.get_cleaned_data_for_step(step) or {}
          add_another = s_data.get('add_another', False)
          if add_another is True:
              index = self.form_list.keyOrder.index(step)+1
              key = "add-another-{0}".format(index)
              self.form_list.insert(index, key,
                      wizard_forms.Wizard4)
          return super(Wizard, self).get_next_step(step)
      

      【讨论】:

      • 仍然不起作用...直到现在我还没有注意到这个错误的关键错误(他们后来出现了一步),但它仍然不起作用,因为 self.form_list 是一个实例变量,对基于类的视图的每个新请求都会创建一个新实例。因此,即使存储后端存储了正确的新 form_list,任何时候类在新的(通常是 POST)请求后查看 self.form_list 时,它都找不到该步骤并引发错误。
      【解决方案3】:

      结论是,这是不可能的。我还没有完全弄清楚为什么它有时与前两个解决方案一起工作,但是在深入研究表单向导的代码之后,很明显每个请求都会重新初始化实例表单列表(嗯,从技术上讲它是一个新实例),因此即使您在存储中更新列表,或者在 get_form_list() 中更新它,也有 一些 调用直接命中实例变量而不是通过get_form_list() 并且需要进行一些重大的重构来调整它。

      我为这个项目选择了另一条路线,但可能很快会为此尝试整合一些东西。

      【讨论】:

        猜你喜欢
        • 2012-05-22
        • 2015-09-03
        • 2013-10-04
        • 2018-06-04
        • 1970-01-01
        • 2013-10-14
        • 2011-12-31
        • 1970-01-01
        • 2010-09-26
        相关资源
        最近更新 更多