How to use Django forms for surveys

1,195 views
Skip to first unread message

Diego De La Vega

unread,
Oct 17, 2016, 7:25:35 AM10/17/16
to Django users
Hi. This is my first question in this group.

My problem is that I have to program a survey application and I would like to have a hint about forms.

The survey is +200 questions long and is divided in multiple subjects (every subject is independent from the others) and mainly consists of numeric (implemented as combo boxes) and text fields..

The main problem is how to do for showing the relevant fields and not the unwanted.

Let me explan this: suppose that when the answer to question 1 is 1, the survey continues with question 2, but if the answer is 2, then the survey continues with question 16 and all the in between questions are skipped.

This is a very simple scenario, but almost all the flow of the survey goes like this, making it complex to follow the order. Sometimes one must skip a few questions but some others, one must skip only one, or a full section of the questions, depending on the answer.

Is there a recommended way to do so? Thanks in advance and sorry for my English, I'm not a native English speaker (I hope all this mess can be understood).

Asad Jibran Ahmed

unread,
Oct 17, 2016, 8:30:52 AM10/17/16
to django...@googlegroups.com
Hi,
 This is a complicated question and I'll do my best to answer it well, but please forgive me if I miss somethings or say something inaccurate. I had a similar project a while back and I did think about a possible solution, something that might be of use to you.

If you want to use something pre-built, I suggest you take a look at https://github.com/eldest-daughter/ed-questionnaire.

If you want something custom, read on.

Firstly, I'd present each question to the user on a separate page. I'd have one Django view called QuestionView. I'd have a URL config similar to this:

url(r'^question/(?P<pk>(\d+))/$', QuestionView.as_view(), name='question')

Next I would come up with a data structure to hold the form configuration. I don't mean a data structure like the ones you see in CS courses (trees, maps, lists, etc). I mean a way to structure your data in a meaningful way. For the scenario you describe, something like this might be a good starting point:

QUESTIONS = [
 {
  "id": 1,
  "question": "Are you a programmer?",
  "options": ["No", "Yes"]
 },

 {

  "id": 2,
  "question": "Which operating system do you use?",
  "options": ["Windows", "Linux", "macOS"]
 },

 {
     "id": 3,
  "question": "Which editor do you use for writing code?",
  "show_if": {"question_id": 1, "answer": "Yes"}
  "options": ["Vim", "Emacs", "Sublime Text", "Other"]
 }
]

In this scenario, question id 3 is only shown if the user selected Yes for question 1. Which means that you'll need to keep track of the answers the user has already taken. Using the session storage for that is one good option.

So each request to the Django app returns a page with a simple HTML page with just one form. The form only has the widgets for the question being answered. The view would take a look at the question it has to present, and then generate a dynamic form based on that. Check out this post for a good description of how to generate dynamic forms: https://jacobian.org/writing/dynamic-form-generation/.

For question 1 in this case, the page would have a form with just 2 radio buttons. When the user submits that form, you'll save their answer somewhere (may the session storage) and then redirect the user to the URL for the next question. To keep it simple, always redirect the user to the next question.

Now comes the conditional logic of whether the user has to answer the question or not. Let's say the user selected No for question 1, then answered question 2 and was redirected to the URL for question 3. At this point, your view looks at the config for question 3. The config says to show this question only if the answer to question 1 was Yes. You check the session storage and see that the user answered No for the first question. So the user shouldn't have to answer this question. You simply redirect the user to question 4, and this entire logic is checked again.

Of course this is only the starting point. An application like this is going to get complicated, and you seem to indicate there is more complicated logic involved than just the simple "Only show this question if that question had and answer matching X". But this is a reasonable starting point for something like this. As you develop your application further you'll learn much more about the specific problem you're solving and come up with much better ways of solving it.

Hopefully this large wall of text made some sense! Let me know if I can explain something more. Hopefully this will be of some use to you.
Regards,

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/55fd589d-1638-4d75-9026-c098ee7729eb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Diego De La Vega

unread,
Oct 19, 2016, 7:49:54 PM10/19/16
to Django users
I think you understood every word I wrote and every problem I had to face. I will see what ed-questionnaire has to offer, but I think that I must code very much.
Now I'm doing the survey with the Delphi-like Lazarus IDE (because I know Pascal very well) and it's easy to follow the control of the flow by enabling every field I need when I exit each field after entering the answer. The disadvantage is that I have to recompile the program every time a bug is discovered (and there are full of them in more than 200 fields!). Finally, this program end up running well after four days of fixing bugs, but I was searching for a method to only fix a .py file instead of recompiling.
I appreciate very much your suggestion and thank you very much!
Diego
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

Petite Abeille

unread,
Oct 19, 2016, 8:02:10 PM10/19/16
to django...@googlegroups.com

> On Oct 17, 2016, at 4:37 AM, Diego De La Vega <aiwil...@gmail.com> wrote:
>
> The main problem is how to do for showing the relevant fields and not the unwanted.

Use TypeForm and call it a day :D

https://www.typeform.com/help/what-is-logic-jump/



James Schneider

unread,
Oct 19, 2016, 8:11:18 PM10/19/16
to django...@googlegroups.com
Django FormTools may be another option, specifically the FormWizard: https://django-formtools.readthedocs.io/en/latest/wizard.html

However, unless you have a very simple and deterministic way to figure out the next question, it will likely turn in to a coding nightmare. The step skipping has a bit of a learning curve to it. The FormWizard was likely built with shorter and more linear workflows in mind. 

Note that this package was included in Django core up until 1.7, this package is (literally) the same thing, just broken out into a separate package (most users did not use this functionality and it bloated the code base if I remember the comments in the release notes).

While this can be super robust, it will probably not be easy.

-James


 

Diego De La Vega

unread,
Oct 20, 2016, 12:28:19 PM10/20/16
to Django users
I'll take a look to FormTools also. The next question is always deterministic and going forward in the survey, but the path maybe a little trickier, depending on ranges of answers of one or more questions.
Thanks a lot.
Diego

Luis Zárate

unread,
Oct 26, 2016, 5:19:48 PM10/26/16
to django...@googlegroups.com
Hi, we are developing something like you want, but it's a premature project right now, maybe in few months we launch our first stable version (survey monkey be aware...), the project home page is

https://github.com/solvo/derb , see development branch for a updated version.

So if you are interested in development let me know.
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/235bd523-c4bc-4849-b0fb-24f53b7094b3%40googlegroups.com.

> For more options, visit https://groups.google.com/d/optout.
>

--
"La utopía sirve para caminar" Fernando Birri



Reply all
Reply to author
Forward
0 new messages