multi-page survey

38 views
Skip to first unread message

Benjamin Ward

unread,
Oct 13, 2009, 2:50:55 AM10/13/09
to django...@googlegroups.com

Hi All,

has anyone had any luck at splitting a large survey over multiple pages (doing so in some sort of dynamic way)?

I'm supposed to make a 210 question a bit more user friendly. also, a 210 question survey in one form/page has a page file size of almost 5MG!

Anyway, I've been banging my head at it all day and would love some help, code snippets, anything.

I've started with simply trying to just get one question to a page, by passing the list for forms returned from survey.forms.forms_for_survy to a class of FromWizard but it borks complaining that "form_list should be a list of Form classes (not instances)."

Is a multipage survey possible with using the FromWizard or am i barking up the wrong tree?

Thanks in advance all.

ben :-)

yml

unread,
Oct 13, 2009, 8:43:26 AM10/13/09
to django-survey
Hello,

Each time I had this kind of need I end up splitting the survey in
several smaller survey so I have never really investigate this.
However your approach seems reasonable to me FormWizard combine with
an additional setting called defining the number of questions per page
should be all you need. This being said the transition to this will
not be as straight forward as you might think. As pointed in the
documentation [1] FormWizard takes a form list as argument so you will
need to find a way to create this list instead of a single monolithic
form.

This is my 2 cts...
Regards,
--yml

[1] http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/#ref-contrib-formtools-form-wizard

Benjamin Ward

unread,
Oct 14, 2009, 3:59:26 AM10/14/09
to django...@googlegroups.com
Hi yml, and others,

On Tue, Oct 13, 2009 at 11:43 PM, yml <yann....@gmail.com> wrote:

Hello,

Each time I had this kind of need I end up splitting the survey in
several smaller survey

yes, i see that multiple-surveys joined together via FormWizard is a possible approach, i will try this today.

 
so I have never really investigate this.
However your approach seems reasonable to me FormWizard combine with
an additional setting called defining the number of questions per page
should be all you need. This being said the transition to this will
not be as straight forward as you might think. As pointed in the
documentation [1] FormWizard takes a form list as argument so you will
need to find a way to create this list instead of a single monolithic

If i understand the code correctly isn't the survey form a collection of smaller forms? and forms_from_survey returns a list of those forms, that that is then itereated over to construct the larger monolithic form? It seems that FormWizard wants a list of form definitions (classes) (and here i get really confused - ive never really used the wizard before this) rather that the form instances.

Does anyone have a suggestion as to how to create the list of forms rather than the single monolithic?

There is also a possible approach using JS to show and hide sections, and simulate a page-flow that way. has anyone had any luck with anything like that that?


thanks, Ben :)

Douglas Napoleone

unread,
Oct 15, 2009, 3:23:15 PM10/15/09
to django...@googlegroups.com
I have not tried it yet, but Brett Cannon just posted some VERY
interesting code and a blog writeup:

http://sayspy.blogspot.com/2009/10/i-jquery-ui.html
http://oplop.appspot.com/

I think something like that might work fantastic.
For extremely long forms (multi-meg of html) each section could be
loaded and injected into the form as the user progresses, but still
have only one submit and final django form for handling the
processing. Much easier than having to handle each page containing
hidden fields for previous pages, or dealing with people whom only
took PART of a survey.
It also exposes people to thing up front.

I like the idea of not being able to go back to a previous section
once you complete it but that is configurable (Brett had to do
something special to make it work that way).

-Doug


>
> thanks, Ben :)
>
> >
>

Paddy Joy

unread,
Oct 25, 2009, 5:46:39 PM10/25/09
to django-survey
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
Reply all
Reply to author
Forward
0 new messages