我有一个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
答案 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),但是很好。