tags:

views:

53

answers:

1

Hello,

I've been learning django off and on for a few years now and consider myself an advanced beginner, ha. I'm working on a "weighted questionnaire" (that's the best name I can give it anyway) for a client and have gone in circles about where to go with it.

The client has come up with a series of yes or no questions and depending on the answer, certain weightings will be applied. At the end upon submission, I need to check for answers and add up the weightings than show a report with suggested products based on the weightings. The weightings are really just products with certain number values for each question.

For example:

"Do you smoke?"

If answered "yes", then apply the following: Core(1), Alpha(4), Liver(2), Jade(1), Rejuve(4)

I've setup initial models and admin but am kind of stumped with how to write the views. They'll be able to add questions with desired answers, then as many weightings (which are foreign keyed to products) and values per question as they want.

Here are my models:

from django.db import models
from src.products.models import Product

"""
    This app has 'yes' or 'no' questions.  Each question has several 'weightings'
    atached to it which are tallied at the end to recommend specific products
    to the user doing the questionairre.
"""

class Question(models.Model):

    """Yes or no questions to gether enough info to recommend products via the weightings."""

    ANSWER_CHOICES = (
        ('y', 'Yes'),
        ('n', 'No'),
    )

    GENDER_CHOICES = (
        ('a', 'All'),
        ('m', 'Male'),
        ('f', 'Female'),
    )

    question_text = models.CharField(
        help_text="The text to be displayed for the question",
        max_length=300
    )
    answer = models.CharField(
        help_text="Weightings will be applied based on the answer. <br> Ex: If 'Yes' is chosen for 'Do you smoke?', then weightings will be applied if the user answers 'Yes'",
        max_length=1,
        choices=ANSWER_CHOICES
    )
    applies_to = models.CharField(
        help_text="Used to filter questions based on gender of user answering the questions.",
        max_length=1,
        choices=GENDER_CHOICES
    )
    order = models.IntegerField(
        help_text="Used to determine the ordering of the questions.  If left blank, the question will appear after those which are ordered.",
        blank=True,
         null=True,
    )

    class Meta:
        verbose_name_plural = 'questions'
        ordering = ['order']

    def __unicode__(self):
        return self.question_text


class Weighting(models.Model):

    """References products with a specified weighting.
        Added up at end to recommend products."""

    question = models.ForeignKey(Question)
    product = models.ForeignKey(Product)
    value = models.IntegerField()

    def __unicode__(self):
        return '%s %s %s' % (self.question, self.product, self.value)

I'm manually creating the forms right now. I figure this is the best way.

So, what'll be the best way to get the answers on post, then compare the answer with the desired answer and get the sum of the weightings across all questions?

The last part with the sum seems the most difficult.

Thoughts and suggestions?

EDIT: Using for reference:

http://questionnaire.corporatism.org/

A: 

What you are trying to do is basically setting up a many-to-many relationship between Question and Product and weighting this relation by adding a field to the relation (value); there's some documentation on that how to that in a django way! I guess you will need one more model to store the answers a user has given, it could be something like that:

from django.contrib.auth.models import User

class Answer(models.Model):
    user = models.ForeignKey(User)
    question = models.ForeignKey(Question)
    answer = models.CharField(choices=ANSWER_CHOICES, max_length=1)

After you have stored the answers I guess the only way will be to iterate over one user's answers, answer by answer and sum up the values if the questions has the right answer!

EDIT: This solution keeps the user's answer's persistent in the database, you have to think yourself what you want to do with them, otherwise you could just store them for a session eg. in a dictionary in request.session.

EDIT: to get the questions in one form try something like:

class QuestionForm(forms.Form):

    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
             initial=None, error_class=ErrorList, label_suffix=':',
             empty_permitted=False):
        super(QuestionForm, self).__init__(data, files, auto_id, prefix,
             initial, error_class, label_suffix, empty_permitted)
        self.questions = Question.objects.all()
        if self.questions:
            for question in self.question:
                self.fields['question_%s' % question.pk] =\
                    forms.ChoiceField(label=question.question_text,
                        choices=[(q.pk, q.answer) for q in question.answer_set.all()])
lazerscience
Thanks for this. I made wrote something similar and its got me headed in the right direction.Now I am struggling to get each question into one form for posting via django's forms and not by hand in the template. May ask a new question.
crobison