【问题标题】:Django: Dynamically set Formset for step in Form WizardDjango:在表单向导中为步骤动态设置表单集
【发布时间】:2014-03-12 06:28:53
【问题描述】:

在我的 Django 视图中,作为Form Wizard 的一部分,我使用的是Formset。每个步骤的向导表单声明如下:

UserFormSet = modelformset_factory(account_models.MyUser,
                                   form=account_forms.MyUserForm, 
                                   extra=5, 
                                   max_num=10, 
                                   can_delete=True)

FORMS = [('userchoice', UserChoiceForm),
         ('user', UserFormSet),]
TEMPLATES = {'userchoice': "account/userchoice.html",
             'user': "account/user.html",}

我想要实现的是:在 UserChoiceForm(第一步)中,可以设置所需用户的数量。我想使用这个值来动态设置 UserFormSet 上的 extra 属性,以便在第二步中只显示所需数量的表单。

我试图通过覆盖向导的 get_form() 方法来做到这一点:

class MyUserWizard(SessionWizardView):
 def get_form(self, step=None, data=None, files=None):
     form = super(MyUserWizard, self).get_form(step, data, files)
     
     # Determine the step if not given
     if step is None:
         step = self.steps.current

     if step == 'user':
         # Return number of forms for formset requested 
         # in previous step.
         userchoice = self.get_cleaned_data_for_step('userchoice')
         num_users = userchoice['num_users']
         CoFunderFormSet.extra = num_users
         return CoFunderFormSet
     return form

使用这种方法,我能够为第二步显示正确数量的表单,但是在尝试发布 Formset 时,我最终遇到了这个错误:

[u'ManagementForm data is missing or has been tampered with']

POST 数据设置了预期的管理表单字段,例如

form-TOTAL_FORMS    u'1'

但我假设 FormWizard 使用的是在初始 FORMS 列表中设置的 Formset,因此管理表单不匹配。

我想知道是否有解决方案,以及是否有办法告诉 FormWizard 在 POST 上使用动态生成的 Formset。

【问题讨论】:

    标签: django django-forms django-formwizard


    【解决方案1】:

    您可以覆盖 get_form_initial,假设您已经像这样设置了 form_list

    form_list = [
            (FIRST_STEP, forms.FirstForm),
            (SECOND_STEP, modelformset_factory(Second_model, form=forms.SecondForm)),
        ]
    
    def get_form_initial(self, step):
            """
            Set extra parameter for step2, which is from clean data of step1.
            """
            if step == self.SECOND_STEP:
                form_class = self.form_list[step]
                data = self.get_cleaned_data_for_step(self.FIRST_STEP)
                if data is not None:
                    extra = get_extra_count(data) # use cleaned data calculate extra
                    form_class.extra = extra
            return super(PackageWizard, self).get_form_initial(step)
    

    【讨论】:

    • 这种方法有效,除非您使用多线程,因为它不是线程安全的。线程安全的方法可能是覆盖 get_form 并动态构建您的表单集。
    【解决方案2】:

    如果您收到此错误消息,

    [u'ManagementForm数据丢失或被篡改']

    确保在您的模板中提供{{ wizard.form.management_form }}

    【讨论】:

      猜你喜欢
      • 2013-01-16
      • 2019-04-18
      • 2021-03-10
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多