Hi,
I recently had the requirement for a 90 question survey spread over
multiple pages (15 in total).
I started building a static version of the survey by creating 15 form
classes and then constructing a FormWizard. This worked but was a
nightmare to manage as I had to change the code everytime the customer
wanted to change the survey.
I needed something dynamic so I downloaded django-survey and modified
it to fit the requirements.
I'm not a python developer and needed something working quickly so my
code is pretty horrible however hopefully some of the things I have
done can give you some ideas to develop your own.
Steps
1. I modified the Question Model to have a field "Page". This field
determines which page the question is displayed on
2. Initialize a FormWizard with an empty form set
urls.py
(r'^interview/(?P<id>\d+)/$', InterviewWizard([]),),
3. In step 0 of the FormWizard we need to create a form class for each
page and append them to the form_list. As you discovered you can't use
form instances so I had to create a function CreateForm(page) that
returns a form class for a particular page.
forms.py
class InterviewWizard(FormWizard):
interview = None
survey = None
def parse_params(self, request, *args, **kwargs):
interview = get_object_or_404(Interview, id=kwargs['id'])
extra_context = { 'interview': interview }
survey = interview.survey
self.interview = interview
self.survey = survey
self.extra_context = extra_context
if self.step == 0:
self.form_list = []
pages = Question.objects.filter(survey=survey).order_by
('page').values_list('page').distinct()
for p in pages:
self.form_list.append(CreateForm(survey, interview,
p))
def done(self, request, form_list):
for f in form_list:
for key in f.cleaned_data:
try:
# get question
qa = Question.objects.get(text=key)
# Create answer and save results
..........
def CreateForm(survey, interview, page):
fields = SortedDict()
for q in survey.questions.filter(page=page[0]).order_by('order',):
field = GetFormField(q)
fields[q.text] = field
return type('myForm', (forms.BaseForm,), { 'base_fields':
fields })
def GetFormField(q):
required = q.required
choices = []
for qa in q.choices.all():
choices.append([qa.text,qa.text])
if q.qtype == "T":
field = forms.CharField(max_length=500, required=required)
elif q.qtype == "A":
field = forms.CharField(max_length=500, required=required,
widget=forms.Textarea)
elif q.qtype == "S":
field = forms.ChoiceField(choices=choices, required=required)
elif q.qtype == "R":
field = forms.ChoiceField(choices=choices, required=required,
widget=forms.RadioSelect)
elif q.qtype == "C":
field = MaxMinMultipleChoiceField(choices=choices,
required=required, choice_num_min=q.choice_num_min ,
choice_num_max=q.choice_num_max , widget=forms.CheckboxSelectMultiple)
else:
field = forms.CharField(max_length=500, required=required)
return field
Hope this helps in some way and if you have any questions jsut let me
know.
Paddy