[Django]-Dynamic FormWizard

5👍

here is how I finished to handle it

first, urls.py :

url(r'^service/create/$','django_th.views.get_form_list', name='create_service'),

then in views.py :

I did :

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)

this permits to define 5 steps with :

  • 3 knowns Form (ProviderForm, ConsummerForm, ServicesDescriptionForm
  • 2 unknown ones (DummyForm twice in fact) that will be handle dynamically below

the forms.py which provides the DummyForm :

class DummyForm(forms.Form):
    pass

the next step is to get the data from ProviderForm, get the service I selected from it, and load the for of this selected service :

in my views.py :

class UserServiceWizard(SessionWizardView):

    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]
            #services are named th_<service>
            #call of the dedicated <service>ProviderForm
            form = class_for_name('th_' + service_name.lower() + '.forms',
                  service_name + 'ProviderForm')
       elif self.steps.current == '3':
            service_name = str(data['consummer']).split('Service')[1]
            #services are named th_<service>
            #call of the dedicated <service>ConsummerForm
            form = class_for_name('th_' + service_name.lower() + '.forms',
                  service_name + 'ConsummerForm')
        context = super(UserServiceWizard, self).get_context_data(form=form,
                                  **kwargs)
    return context

here :

  • __init__ load the data from get_form_list function I defined in urls.py
  • in get_context_data I need to change the DummyForm in step 1 and 3 from the service I chose in the dropdown of ProviderForm and ConsummerForm. As the service is named ‘FoobarService’, I split ‘Service’ to make the call of the form of the service Foobar(Consummer|Provider)Form with class_for_name() below :

class_for_name :

def class_for_name(module_name, class_name):
   m = importlib.import_module(module_name)
   c = getattr(m, class_name)
   return c

Finally :

with all of this I’m able to dynamically change the form on the fly at any step, in fact I decide to do it for step 1 and 3 but that can be adapted for any step 😉

Leave a comment