django-domande

django app to represent generic questions on forms


License
Other
Install
pip install django-domande==0.1.2

Documentation

domande

Logo by @aurorachiarello

Build Status PyPi downloads

A plugable Django app to represent a generic questions on forms.

Dependencies

Here are the list of dependencies;

Installation

For stable PyPI version

pip install django-domande

To get development version

pip install git+git://github.com/bulkan/django-domande.git

In your settings.py file change INSTALLED_APPS and add;

INSTALLED_APPS = [
   ...
   'crispy-forms'   # need to add this for it's template tags to load
   'polymorphic',   # provides admin templates
   'domande'
   ...
]

Note I'm assuming you have South already installed if not add south to INSTALLED_APPS

General

domande uses model inheritence to simplify relationships to a list of questions and it does this with the help of django-polymorphic. At the moment domande supports two types of questions that are rendered differently by their accompanying forms.

A TextQuestion were the answer is a text and a ChoiceQuestion were the answer is chosen by a set of Choices. TextQuestion and ChoiceQuestion are subclasses of Question.

Example Usage

Models

Create a model with a ManyToManyField to domande.models.Question. For example a Questionnaire;

from django.db import models
from django.contrib.contenttypes import generic

from domande.models import Question, Answer

class Questionnaire(models.Model):
    name = models.CharField(max_length=256)

    questions = models.ManyToManyField(Question)

Once you add a ManyToManyField to domande.models.Question and register your model with the django admin interface the questions field will be handled uniquely. As domande.models.Questions is the parent model when you create a new one the admin inteface will display an additional step of choosing the child model to create an instance of.

View

Now you need to render the list of Questions in a view;

def questionnaire_view(request):

    # for sake of example use .get
    questionnaire = Questionnaire.objects.get(id=1)

    forms = [q.get_form()(prefix=str(q.id),
                content_object=request.user,
                question=q, form_tag=False)
                   for q in questionnaire.questions.all().get_real_instances()
               ]

    # form is a list of TextQuestionForm or ChoiceQuestionForm

domande's forms accept a content_object that is used when it creates and saves an Answer. domande doesn't know in advance what type of user or entry model you have so it uses django's builtin ContentType framework to solve this.

In the above example it uses request.user.

Template

in the template render the forms like so;

{% load crispy_forms_tags %}

<form method="post">
    {% for form in forms %}
        {% crispy form %}
    {% endfor %}
</form>

to process the validity of the forms and save the Answers;

def save_view(request, questionnaire):
    # for sake of example use .get
    questionnaire = Questionnaire.objects.get(id=questionnaire)

    forms = [q.get_form()(request.POST or None,
                prefix=str(q.id),
                content_object=request.user,
                question=q, form_tag=False)
                    for q in questionnaire.questions.all().get_real_instances()
            ]

    forms_are_valid = []

    for form in forms:
        forms_are_valid.append(valid)
        valid = form.is_valid()
        if valid:
            t = form.save()

    forms_are_valid = all(forms_are_valid)

Each question model in domande has an Answer model that relates to it. A ChoiceQuestion will use a ChoiceAnswer and a TextQuestion will use a ChoiceAnswer.

Development

  • Fork this repo, create a virtualenv and clone your fork. Then install the requirements

    pip install -r requirements.txt

  • If you have changed the models then create a migration;

    django-admin.py schemamigration --settings=domande.settings --pythonpath=$PWD

  • Please make sure existing tests pass and feel free to add more tests as you see fit.

    django-admin.py test --settings='tests.test_settings' --pythonpath=$PWD

  • Submit Pull Request