djangodjango-formsdjango-formwizard

Django Form Wizard Skip Multiple Steps with Conditional Logic


Is there some way to skip multiple steps in Django's Form Wizard (i.e. SessionWizardView)?

I know it is possible to use condition_dict to produce the following form display logic: Page 1 -> Page 3

#urls.py 
path('main/', MyWizard.as_view(set_of_forms, condition_dict={'1': view_condition} ))

What I would like to do is the following: Page 1 --> Page 4

Presumably, adding a condition_dict based on the content of Page 1 should work to skip Page 3, but it doesn't work. For example:

#urls.py 
path('main/', MyWizard.as_view(set_of_forms, condition_dict={'1': view_condition, '2': view_condition2,} ))

I am truly stumped on how to crack this nut. Any guidance that you can provide would be GREATLY appreciated.


Solution

  • The typical way to specify when FormWizard skips a step is to use a condition_dictionary. Django uses the structure to only include the form for a step when the conditions (set as callables)

    # I always specify index values for steps so that all functions can share them
    STEP_ONE = u'0'
    STEP_TWO = u'1'
    STEP_THREE = u'2'
    
    
    def MyWizard(SessionWizardView):
        # Your form wizard itself; will not be called directly by urls.py, but rather wrapped in a function that provide the condition_dictionary
        _condition_dict = { # a dictionary with key=step, value=callable function that return True to show step and False to not
            STEP_ONE: return_true, # callable function that says to always show this step
            STEP_TWO: check_step_two, # conditional callable for verifying whether to show step two
            STEP_THREE: return_true, # callable function that says to always show this step
        }
        _form_list = [ # a list of forms used per step
            (STEP_ONE,your_forms.StepOneForm),
            (STEP_TWO, your_forms.StepTwoForm),
            (STEP_THREE, your_forms.StepThreeForm),
        ]
        ...
    
    
    def return_true(wizard): #  callable function called in _condition_dict
        return True # a condition that is always True, for when you always want form seen
    
    def check_step_two(wizard): #  callable function called in _condition_dict
        step_1_info = wizard.get_cleaned_data_for_step(STEP_ONE)
        # do something with info; can retrieve for any prior steps
        if step_1_info == some_condition:
            return True # show step 2
        else: return False # or don't
    
    ''' urls.py '''
    
    your_form_wizard = MyWizard.as_view(MyWizard._form_list,condition_dict= MyWizard._condition_dict)
    
    urlpatterns = patterns('',
        ...
        url(r'^form_wizard_url/$', your_form_wizard, name='my-form-wizard',) 
    )