I use Django 1.4.8
I am able to dynamically change the form from a choice made on the previous step, but now I need to be more accurate.
Effectively, in my form "step 0", I have a dropdown from where I select a value, then at step 2, I need to load the same data as "step 0" without the selected value at step 0.
I did it like this :
urls.py :
# wizard
url(r'^service/create/$',
UserServiceWizard.as_view([ProviderForm,
DummyForm,
ConsummerForm,
DummyForm,
ServicesDescriptionForm]),
views.py
def get_form(self, step=None, data=None, files=None):
"""
change the form instance dynamically from the data we entered
at the previous step
"""
#
if step is None:
step = self.steps.current
if step == '1':
prev_data = self.get_cleaned_data_for_step('0')
service_name = str(prev_data['provider']).split('Service')[1]
class_name = 'th_' + service_name.lower() + '.forms'
form_name = service_name + 'ProviderForm'
form_class = class_for_name(class_name, form_name)
form = form_class(data)
elif step == '2':
data = self.get_cleaned_data_for_step('0')
form = ConsummerForm(initial={'provider': data['provider']})
# EDIT 10/16 @ 10:00
# to track what's wrong I added
print form['consummer'].errors #return nothing
print form.is_valid() #return false
print "form.non_field_errors ", form.non_field_errors() #return nothing
elif step == '3':
prev_data = self.get_cleaned_data_for_step('2')
service_name = str(prev_data['consummer']).split('Service')[1]
class_name = 'th_' + service_name.lower() + '.forms'
form_name = service_name + 'ConsummerForm'
form_class = class_for_name(class_name, form_name)
form = form_class(data)
else:
form = super(UserServiceWizard, self).get_form(step, data, files)
return form
my forms is :
class ServiceChoiceForm(forms.Form):
def activated_services(self, provider=None):
"""
get the activated services added from the administrator
"""
services = ServicesActivated.objects.filter(status=1)
choices = []
datas = ()
if provider is not None:
services = services.exclude(name__exact=provider)
for class_name in services:
datas = (class_name, class_name.name.rsplit('Service', 1)[1])
choices.append(datas)
return choices
class ProviderForm(ServiceChoiceForm):
provider = forms.ChoiceField()
def __init__(self, *args, **kwargs):
super(ProviderForm, self).__init__(*args, **kwargs)
self.fields['provider'].choices = self.activated_services()
class ConsummerForm(ServiceChoiceForm):
consummer = forms.ChoiceField()
def __init__(self, *args, **kwargs):
super(ConsummerForm, self).__init__(*args, **kwargs)
# get the list of service without the one selected in
# the provider form
self.fields['consummer'].choices = self.activated_services(
self.initial['provider'])
Now what's happened :
when I'm on the form "step 2" and submit the data... I return to "step 2" indefinitely
If I dont put the part of elif step == '2'
in the get_form()
and put the same code in the form form the ConsummerForm :
self.fields['consummer'].choices = self.activated_services()
then the process continues but it's not what I want :(
last things
"=
I notice that the get_form()
is called too many times after the "step 0" : in fact 4 times .
I tracked that with a print form,step
in get_form()
but the form is never the expected one.
If anyone can explain my how I can fix the behavior of the infite loop in the wizard ; i would appreciate a lot ;)
I found the solution :
at step 2 I have to do this
elif step == '2':
step0_data = self.get_cleaned_data_for_step('0')
form = ConsummerForm(
data, initial={'provider': step0_data['provider']})
instead of
elif step == '2':
data = self.get_cleaned_data_for_step('0')
form = ConsummerForm(initial={'provider': data['provider']})
because In the 1rst I didnt overwrite the "data" dict like i did by accident in 2nd piece of code...
now everything works GREAT !