问题 如何将以前的表单数据传递给FormWizard中DynamicForm的构造函数


我有一个FormWizard,我需要第一个表单中的数据传递给第二个表单的构造函数,以便我可以构建一个动态表单。

我可以通过FormWizard的process_step获取第一个表单的数据。

我使用字段列表的数据库调用创建第二个窗体的字段。

class ConditionWizardDynamicQuestions(forms.Form):

    def __init__(self, DynamicQuestions=None, *args, **kwargs):
       super(ConditionWizardDynamicQuestions, self).__init__(*args, **kwargs)
       questions = Question.objects.filter(MYDATA = DATA_FROM_1STFORM)
       for q in questions:
            dynField = FieldFactory(q)
            self.fields[q.label] = dynField

我怎么能越过 DATA_FROM_1STFORM ?


我的结果代码: 我放弃了 在里面 的形式,并将其切换到CreateQuestions def。然后使用向导的get_form覆盖来在创建后更改表单。

class ConditionWizard(SessionFormWizard):
    def get_form(self, request, storage, step=None, data=None, files=None):
        form = super(ConditionWizard, self).get_form(request, storage, step, data, files)
        stepIndex = self.get_step_index(request, storage, step)
        if stepIndex == 1:
            form.CreateQuestions(request.session["WizardConditionId"])
        if stepIndex == 3:
            form.fields['hiddenConditionId'].initial = request.session["WizardConditionId"]
            form.fields['medicationName'].queryset = Medication.objects.filter(condition = request.session["WizardConditionId"])
        return form

2793
2017-10-15 07:01


起源



答案:


FormWizard已经将每个前一个表单中的数据传递给下一个表单。如果你想获取那些数据以实例化一个类(例如,如果一个表单有它需要的特殊关键字参数),一种方法是通过覆盖来获取querydict get_form 在您的表单向导类中。例如:

class SomeFormWizard(FormWizard):
    def get_form(self, step, data=None):
        if step == 1 and data: # change this to whatever step requires
                               # the extra data
            extra_data = data.get('key_from_querydict')
            if extra_data:
                return self.form_list[step](data,
                                            keyword_argument=extra_data,
                                            prefix=self.prefix_for_step(step),                                                                                                                                            
                                            initial=self.initial.get(step, None))
        # Fallback for the other forms.
        return self.form_list[step](data,
                                    prefix=self.prefix_for_step(step),                                                                                                                                            
                                    initial=self.initial.get(step, None))

请注意,您也可以覆盖 parse_params(self, request, *args, **kwargs) 在FormWizard中访问url / request数据,就像你在视图中一样,所以如果你有请求数据(request.user,例如)所有表格都需要,从那里获取数据可能更好。

希望这可以帮助。


5
2017-11-11 17:29



我遇到了将数据从第1步传递到第3步的问题,但您的解决方案非常有用且富有洞察力。 - BozoJoe
你遇到了什么问题? AFAIK它应该允许您访问所有以前形式的所有数据 - 也就是说,步骤3应该包含步骤1和步骤2中的数据。 - Jeremy Sandell
我的问题是我试图使用向导中的初始化并覆盖表单 在里面。我转而使用get_form,世界越来越清晰了:) - BozoJoe


答案:


FormWizard已经将每个前一个表单中的数据传递给下一个表单。如果你想获取那些数据以实例化一个类(例如,如果一个表单有它需要的特殊关键字参数),一种方法是通过覆盖来获取querydict get_form 在您的表单向导类中。例如:

class SomeFormWizard(FormWizard):
    def get_form(self, step, data=None):
        if step == 1 and data: # change this to whatever step requires
                               # the extra data
            extra_data = data.get('key_from_querydict')
            if extra_data:
                return self.form_list[step](data,
                                            keyword_argument=extra_data,
                                            prefix=self.prefix_for_step(step),                                                                                                                                            
                                            initial=self.initial.get(step, None))
        # Fallback for the other forms.
        return self.form_list[step](data,
                                    prefix=self.prefix_for_step(step),                                                                                                                                            
                                    initial=self.initial.get(step, None))

请注意,您也可以覆盖 parse_params(self, request, *args, **kwargs) 在FormWizard中访问url / request数据,就像你在视图中一样,所以如果你有请求数据(request.user,例如)所有表格都需要,从那里获取数据可能更好。

希望这可以帮助。


5
2017-11-11 17:29



我遇到了将数据从第1步传递到第3步的问题,但您的解决方案非常有用且富有洞察力。 - BozoJoe
你遇到了什么问题? AFAIK它应该允许您访问所有以前形式的所有数据 - 也就是说,步骤3应该包含步骤1和步骤2中的数据。 - Jeremy Sandell
我的问题是我试图使用向导中的初始化并覆盖表单 在里面。我转而使用get_form,世界越来越清晰了:) - BozoJoe


我通过覆盖WizardView的get_form_kwargs解决了这个问题。它通常只返回一个get_form填充的空字典,因此通过覆盖它来返回包含您需要预先填充的数据的字典,您可以将kwargs传递给表单init。

def get_form_kwargs(self, step=None):
    kwargs = {}
    if step == '1':
        your_data = self.get_cleaned_data_for_step('0')['your_data']
        kwargs.update({'your_data': your_data,})
    return kwargs

然后,在你的形式 在里面 你可以在调用super之前弹出kwarg的方法:

self.your_data = kwargs.pop('client', None)

8
2017-10-22 15:04





在视图中覆盖表单向导的get_form_kwargs方法

view.py

class FormWizard(SessionWizardView):
    def get_form_kwargs(self, step=None):
        kwargs = {}
        if step == '1':
            step0_form_field = self.get_cleaned_data_for_step('0')['previous_form_field_data']
            kwargs.update({'step0_form_field': step0_form_field})
        return kwargs 

通过弹出从上一个字段获得的数据来覆盖表单的init以创建动态字段。

forms.py

class MyForm(forms.Form):
    #some fields

class MyForm1(forms.Form):
    def __init__(self, *args, **kwargs):
        extra = kwargs.pop('step0_form_field')
        super(MyForm1, self).__init__(*args, **kwargs)

        for i in range(extra):
            self.fields['name_%s' % i] = forms.CharField()

3
2017-08-28 08:29





我最近使用django表单向导,我正在解决类似的问题。我不认为你可以传递数据 在里面但是,你可以做的是覆盖 在里面 构造函数:

next_form = self.form_list[1]

# let's change the __init__
# function which will set the choices :P
def __init__(self, *args, **kw):
    super(next_form, self).__init__(*args, **kw)
    self.fields['availability'].choices = ...
next_form.__init__ = __init__

令人讨厌的是,在python中你不能一次声明和分配一个函数并且必须把它放在命名空间中(除非你使用lambdas),但是哦。


0
2017-10-16 23:52



我不确定我会效仿。这段代码是否覆盖了 在里面 子类FormWizard的?这如何让我从步骤1到步骤2获取数据? - BozoJoe
不,它凌驾于 在里面 下一个表格。请注意它是如何表示self.fields ['availability']。choices = ...,现在而不是......你可以放置你想传递的任何数据 - George Karpenkov
我已经有了“next_form” 在里面 覆盖,所以我仍然没有看到你从以前形式的向导传递数据。 - BozoJoe
哦,这个代码必须在向导的process_step方法内 - 这样你就可以获得self.form_list [0] .cleaned_data,并以新的为基础 在里面 在那 - George Karpenkov
好的,明白了,让我试一试。 - BozoJoe