Django FormWizard cómo cambiar el form_list dinámicamente

Soy capaz de llamar dinámicamente a un formulario relacionado con los datos que elegí del paso anterior .

Pero cuando estoy en el método done , puedo ver que mi form_list permanece sin cambios.

Aquí esta lo que hice :

 def get_form_list(request, form_list=None): if form_list is None: form_list = [ProviderForm, DummyForm, ConsummerForm, DummyForm, \ ServicesDescriptionForm] return UserServiceWizard.as_view(form_list=form_list)(request) class UserServiceWizard(SessionWizardView): instance = None def __init__(self, **kwargs): self.form_list = kwargs.pop('form_list') return super(UserServiceWizard, self).__init__(**kwargs) def get_form_instance(self, step): if self.instance is None: self.instance = UserService() return self.instance def get_context_data(self, form, **kwargs): data = self.get_cleaned_data_for_step(self.get_prev_step( self.steps.current)) if self.steps.current == '1': service_name = str(data['provider']).split('Service')[1] form = class_for_name('th_' + service_name.lower() + '.forms', service_name + 'ProviderForm') self.form_list['1'] = form #here my form is correctly change I can see elif self.steps.current == '3': service_name = str(data['consummer']).split('Service')[1] form = class_for_name('th_' + service_name.lower() + '.forms', service_name + 'ConsummerForm') self.form_list['3'] = form context = super(UserServiceWizard, self).get_context_data(form=form, **kwargs) return context def done(self, form_list, **kwargs): print self.form_list #here form_list contains ProviderForm, DummyForm, ConsummerForm, DummyForm, ServicesDescriptionForm 

en el paso 0 mi form_list está bien:

 {u'0': , u'1': , u'2': , u'3': , u'4': } 

en el paso 1 mi form_list está bien: podemos ver que la segunda forma es la esperada

     {u'0': , u'1': , u'2': , u'3': , u'4': } 

    en el paso 2 mi form_list es ko; igual que el paso 0: mi segunda forma es regresar a DummyForm

     {u'0': , u'1': , u'2': , u'3': , u'4': } 

    ¿Cómo puedo hacer para cambiar self.form_list y mantener el cambio que hice en get_context_data hasta el final del asistente y no en cada paso?

    EDITAR aquí es el código completo que funciona bien con la sugerencia de Rohan:

     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': # change the form 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 == '3': # change the form 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: # get the default form form = super(UserServiceWizard, self).get_form(step, data, files) return form def done(self, form_list, **kwargs): """ Save info to the DB The process is : 1) get the infos for the Trigger from step 0, 2, 4 2) save it to TriggerService 3) get the infos from the "Provider" and "Consummer" services at step 1 and 3 4) save all of them """ # get the datas from the form for TriggerService i = 0 for form in form_list: # cleaning data = form.cleaned_data # get the service we selected at step 0 : provider if i == 0: trigger_provider = UserService.objects.get( name=data['provider'], user=self.request.user) model_provider = get_service_model('provider', data) # get the service we selected at step 2 : consummer elif i == 2: trigger_consummer = UserService.objects.get( name=data['consummer'], user=self.request.user) model_consummer = get_service_model('consummer', data) # get the description we gave for the trigger elif i == 4: trigger_description = data['description'] i += 1 # save the trigger trigger = TriggerService( provider=trigger_provider, consummer=trigger_consummer, user=self.request.user, status=True, description=trigger_description) trigger.save() model_fields = {} # get the datas from the form for Service related # save the related models to provider and consummer i = 0 for form in form_list: model_fields = {} data = form.cleaned_data # get the data for the provider service if i == 1: for field in data: model_fields.update({field: data[field]}) model_fields.update({'trigger_id': trigger.id, 'status': True}) model_provider.objects.create(**model_fields) # get the data for the consummer service elif i == 3: for field in data: model_fields.update({field: data[field]}) model_fields.update({'trigger_id': trigger.id, 'status': True}) model_consummer.objects.create(**model_fields) i += 1 return HttpResponseRedirect('/') 

    En lugar de cambiar la lista de formularios, etc. en get_context_data() , creo que sería más apropiado implementar el método get_form() en la vista del asistente y devolver una instancia de formulario diferente dependiendo del paso y los datos anteriores.

    Algo como esto:

     class UserServiceWizard(SessionWizardView): instance = None def get_form(self, step=None, data=None, files=None): if step is None: step = self.steps.current prev_data = self.get_cleaned_data_for_step(self.get_prev_step( self.steps.current)) if step == '1': service_name = str(prev_data['provider']).split('Service')[1] form_class = class_for_name('th_' + service_name.lower() + '.forms', service_name + 'ProviderForm') form = form_class(data) elif step == '3': service_name = str(prev_data['consummer']).split('Service')[1] form_class = class_for_name('th_' + service_name.lower() + '.forms', service_name + 'ConsummerForm') form = form_class(data) else: form = super(UserServiceWizard, self).get_form(step, data, files) return form 

    El truco aquí es no cambiar la longitud de la lista de formularios (lo que ha hecho correctamente), sino simplemente cambiar la instancia de formulario. Django ha proporcionado una forma de anular el método get_form() para este propósito. Django respetará este método y siempre lo usará para obtener la instancia de formulario para el método.

    No estoy seguro de si es la solución que está buscando, pero si modifica form_list en process_step en lugar de en get_context_data, debería funcionar. Tendrá que cambiar su código ya que process_step se ejecuta después de enviar un formulario.

    De acuerdo con Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/formtools/form-wizard/ process_step es el “Enganche para modificar el estado interno del asistente”, al menos para las vars self.kwargs (en De hecho, su formulario_list está en self.kwargs [“form_list”]) He comprobado que todas las modificaciones en get_context_data se ignoran, por lo que creo que self.form_list debería comportarse de la misma manera.