views:

318

answers:

1

Hi,

I am trying to create a multipage form, where the number of field elements on the second page is defined by the answers given on the first.

I have a formWizard set up and my understanding is that I need to use process_step() to alter the setup for the next page. I can either extend an existing form definition to add more elements, or merge 2 or more form definitions together to produce the correct number of form elements, but i have no idea how to do this.

Eg

Page 1 - Select interested subjects:

Page 2 - for each subject: ask relevant questions. Questions are defined as seperate forms in application, but need to be shown on one page, or merged into a single form.

Any help much appreiciated.

Spender

A: 

Spender,

At least at the moment I don't know a way of merging multiple forms onto one page in a FormWizard. In django 1.2 you will be able to include FormSets as steps in FormWizards (as per this ticket) but those only deal with multiple copies of identical forms, not compilations of many forms. But there is a way to do what you ask:

from django.contrib.formtools.wizard import FormWizard
from django import forms

class SubjectForm(forms.Form):
    subjects = forms.MultipleChoiceField(choices = (('language', 'language'), 
                 ('sport','sport')))

class RelatedQForm(forms.Form):
    """Overload the __init__ operator to take a list of forms as the first input and generate the 
    fields that way."""
    def __init__(self, interested_subjects, *args, **kwargs):
     super(RelatedQForm, self).__init__(*args, **kwargs)
     for sub in interested_subjects:
      self.field[sub] = forms.CharField(label = "What do you think about %s" % subject)

class SubjectWizard(FormWizard):
    def done(self, request, form_list):
     process_form_list(form_list)

    def process_step(self, request, form, step):
     if step == 1:
      chosen_subs = form.cleaned_data['subjects']
      self.form_list[1] = RelatedQForm(chosen_subs)

With this code you instantiate your FormWizard as you normally would in the view and then let the wizard class take care of everything behind the scenes.

The general idea is to overload the init class of a "RelatedQForm" to dynamically alter the fields. This code snippet was taken from here. You can make the processing within the init operator as complex as you'd like, read "include the fields from your forms as if-elif blocks inside the for-loop" ... you could probably even figure out a way to strip the fields from your current forms programatically, I'd have to see them to figure it out though.

Your "process_form_list" function will need to loop over the fields using something like:

for field, val in form.cleaned_data.items():
    do_stuff

Hope this gets you on your way :)

JudoWill