Django: Dynamically set Formset for step in Form Wizard
django, django-forms, django-formwizard
Solution
You can override `get_form_initial`, assume you have already set your `form_list` like this:
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)
Problem
As part of a Form Wizard in my Django view I am using a Formset. The wizard's forms for each step are declared like this: ``` 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",} ``` What I am trying to achieve is this: In UserChoiceForm (first step) the number of required users can be set. I want to use this value to dynamically set the extra attribute on UserFormSet so that only the required number of Forms gets displayed in the second step. I am trying to do this by overriding the wizard's get_form() method: ``` 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 ``` With this approach I am able to get the right amount of forms displayed for the second step, but when trying to post the Formset I am ending up with this error: ``` [u'ManagementForm data is missing or has been tampered with'] ``` The POST data has the expected management form fields set, e.g. ``` form-TOTAL_FORMS u'1' ``` but I assume the FormWizard is using the Formset that was set in the initial FORMS list and therefore the management forms do not match. I was wondering if there is a solution to this and if there is a way to tell the FormWizard to use the dynamically generated Formset on POST instead.