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

时间:2010-10-15 07:01:30

标签: django django-formwizard

我有一个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


我的结果代码: 我放弃了表单的 init ,并将其切换到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

4 个答案:

答案 0 :(得分:8)

我通过覆盖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

然后,在您的表单 init 方法中,您可以在调用super之前弹出kwarg:

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

答案 1 :(得分:5)

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

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))

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

希望这有帮助。

答案 2 :(得分:3)

在视图

中覆盖表单向导的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 :(得分:0)

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

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),但是很好。