I'm trying to pass data from my view to my form class using WizardView.
Without WizardView, I do this using get_forms_kwargs()
like the below:
def get_form_kwargs(self):
kwargs = super(MenuAddWizard, self).get_form_kwargs()
kwargs.update({'month': self.kwargs['month']})
return kwargs
And in my form class I use:
def __init__(self, *args, **kwargs):
self.month = kwargs.pop('month', None)
All good - I'm able to use 'month' for validation in e.g. clean()
.
When I'm using WizardView though, I'm specifying the step in get_forms_kwargs()
as follows, per the docs:
def get_form_kwargs(self, step=0):
kwargs = super(MenuAddWizard, self).get_form_kwargs()
kwargs.update({'month': self.kwargs['month']})
return kwargs
My get_form()
doesn't like this:
File "python312\Lib\site-packages\formtools\wizard\views.py", line 311, in post
return self.render_next_step(form)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "python312\Lib\site-packages\formtools\wizard\views.py", line 322, in render_next_step
new_form = self.get_form(
^^^^^^^^^^^^^^
File "myproject\views.py", line 1614, in get_form
form = super().get_form(step, data, files)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "python312\Lib\site-packages\formtools\wizard\views.py", line 432, in get_form
return form_class(**kwargs)
^^^^^^^^^^^^^^^^^^^^
TypeError: BaseFormSet.__init__() got an unexpected keyword argument 'month'
Any idea how to properly pass kwargs (or any other way) to a form with Django Form Wizard?
For reference, the full view is below (without get_forms_kwargs()
):
class MenuAddWizard(LoginRequiredMixin, SessionWizardView):
# Either provide form_list as part of .as_view() in urls, or here.
form_list = [MenuInputForm, DayMenuFormSet]
template_name = "menu_add.html"
def get_context_data(self, form, **kwargs):
context = super(MenuAddWizard, self).get_context_data(form=form, **kwargs)
month = self.kwargs['month']
context['month'] = month
return context
def get_form_kwargs(self):
kwargs = super(MenuAddWizard, self).get_form_kwargs()
kwargs.update({'month': self.kwargs['month']})
return kwargs
def get_form(self, step=None, data=None, files=None):
form = super().get_form(step, data, files)
if step is None:
step = self.steps.current
if step == '1':
step_0_cleaned_data = self.get_cleaned_data_for_step('0')
# Using step 0 data, I generate the list to be used for initial; removing logic for brevity and using two example items as test
DayMenuFormSet = formset_factory(form=DayMenuForm, extra=0)
formset = DayMenuFormSet(initial=[{'menu': 'Some example text'}, {'menu': 'This is another test...'}],
data=data)
form = formset
return form
My forms are all inheriting from the standard forms.Form
.
You seem to use a FormSet
, probably made out of your form. Then you need to pass the values through the form_kwargs=…
parameter [Django-doc], so:
def get_form_kwargs(self, *args, **kwargs):
result = super().get_form_kwargs(*args, **kwargs)
result.update(form_kwargs={'month': self.kwargs['month']})
return result
or perhaps simpler:
def get_form_kwargs(self, *args, **kwargs):
return {
**super().get_form_kwargs(*args, **kwargs),
'form_kwargs': {'month': self.kwargs['month']},
}
EDIT: the problem seems to be that you use a FormSet
for a certain step, and a (simple) Form
for other steps.
You should pass the value as month
if it is for a (simple) form, and through form_kwargs
for a FormSet
, so:
class MenuAddWizard(LoginRequiredMixin, SessionWizardView):
# …
def get_form_kwargs(self, step=None, *args, **kwargs):
result = super().get_form_kwargs(step=step, *args, **kwargs)
if str(step) == '0':
result.update(month=self.kwargs['month'])
else:
# if used for a forms in a FormSet, probably not
# result.update(form_kwargs={'month': self.kwargs['month']})
pass
return result
# …
Note: Since PEP-3135 [pep], you don't need to call
super(…)
with parameters if the first parameter is the class in which you define the method, and the second is the first parameter (usuallyself
) of the function.