[Answer]-How to create a dynamic form using WizardView (Django 1.4)?

1👍

Better late than never… I have run into this scenario myself recently and had to override the form’s (for the second step) init method and pass an initial keyword from the WizardView to the form. From there I could conditionally set the choices for a form field.

My own implementation-

views.py

class QuoteWizard(SessionWizardView):
    form_list = [QQFormProductLine, QQProduct, QQProductFluidProperties]
    ...
    def get_form_initial(self, step):
        #pass variables to forms from here
        initial = self.initial_dict.get(step, {})
        if int(step) > 0:
            self.temperature_units, self.measurement_format = self.get_measurement_units()
            initial.update({'measurement_format': self.measurement_format})
        return initial

forms.py

class QQProduct(forms.ModelForm):
    ...
    def __init__(self, *args, **kwargs):
        super(QQProduct, self).__init__(*args, **kwargs)
        units = None 

        if 'initial'in kwargs:
            initial = kwargs.pop('initial')
            if 'measurement_format' in initial:
                units = initial.pop('measurement_format')

        flow_choices = []
        if units == 'imperial':
            flow_units = qq_models.FlowRateUnits()
            flow_units = flow_units.imperial()
        elif units == 'metric':
            flow_units = qq_models.FlowRateUnits()
            flow_units = flow_units.metric()

        for i in flow_units:
            flow_choices.append((i, qq_models.FlowRateUnits.get(i)))
        if len(flow_choices) > 0:
            self.fields['flow_rate_format'].widget.choices = flow_choices

In summary, get_form_initial is a WizardView method that passes initial keywords to the form for a step. In my self.get_measurement_units() method, I call self.get_cleaned_data_for_step(‘0’) and, depending on user input in the first step, change the choices displayed in a choicefield in the second step’s form.

0👍

You can do like this:

views.py:

from django.contrib.formtools.wizard.views import CookieWizardView

class ChoiceWizardView(CookieWizardView):
    def done(self, form_list, **kwargs):
        pass

    def get_form(self, step=None, data=None, files=None):
        form = super(ChoiceWizardView, self).get_form(step, data, files)
        if 'choice_field' in form.fields:
            form1_cleaned_data = self.get_cleaned_data_for_step('0')
            if form1_cleaned_data:
                form.fields['choice_field'].choices = [item for item in form1_cleaned_data.items()]
        return form

urls.py:

from app.forms import Form1, Form2
from app.views import ChoiceWizardView

urlpatterns = patterns('',
    (r'^my_wizard/$', ChoiceWizardView.as_view([Form1, Form2])),
)

It will work. But maybe you chose wrong application architecture?

Leave a comment