Search code examples
djangodjango-formwizard

How to pass previous form data to the constructor of a DynamicForm in FormWizard


I have a FormWizard where I need data from the first form to pass to the constructor of the second form so I can build a dynamic form.

I can get the first form's data via the process_step of the FormWizard.

I create the fields of the second form with a database call of the list of fields.

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

How can I pass over the DATA_FROM_1STFORM ?


my resultant code: I abandoned the init of the form, and switched it to the CreateQuestions def. Then used the wizard's get_form override to alter the form after creation.

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

Solution

  • FormWizard already passes the data from each previous form to the next form. If you want to get that data in order to instantiate a class (for example, if a form has special keyword arguments that it requires), one way of doing it is to grab the querydict by overriding get_form in your form wizard class. For example:

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

    Note that you can also override parse_params(self, request, *args, **kwargs) in FormWizard to access the url/request data, just like you would in a view, so if you have request data (request.user, for instance) that is going to be needed for all of the forms, it might be better to get the data from there.

    Hope this helps.