views:

1617

answers:

3

Alright, I'm at a loss with the Django Forms, as the documentation just doesn't seem to quite cover what I'm looking for. At least it seems to come to a screeching halt once you get past the most rudimentary of forms. I'm more than willing to take a link to good documentation, or a link to a good book that covers this topic, as an answer. Basically, this is how it breaks down, I have 3 models (quiz, questions, answers). I have 20 questions, with 4 potential answers (multi-choice), per quiz. The numbers can vary, but you get the point.

I need to create a form for these items, much like you'd expect in a multiple choice quiz. However, when I create the form by hand in the templates, rather than using django.forms, I get the following:

invalid literal for int() with base 10: 'test'

So I'm trying to mess with the django.forms, but I guess I'm just not grasping the idea of how to build a proper form out of those. Any help would be greatly appreciated, thanks.

For what it's worth here are the models:

class Quiz(models.Model):
    label = models.CharField(blank=True, max_length=400)
    slug = models.SlugField()

    def __unicode__(self):
        return self.label

class Question(models.Model):
    label = models.CharField(blank=True, max_length=400)
    quiz = models.ForeignKey(Quiz)

    def __unicode__(self):
        return self.label

class Answer(models.Model):
    label = models.CharField(blank=True, max_length=400)
    question = models.ForeignKey(Question)
    correct = models.BooleanField()

    def __unicode__(self):
        return self.label
+2  A: 

First, you create a ModelForm for a given Model. In this example I'm doing it for Quiz but you can rinse and repeat for your other models. For giggles, I'm making the "label" be a Select box with preset choices:

from django.models import BaseModel
from django import forms
from django.forms import ModelForm

CHOICES_LABEL = (
    ('label1', 'Label One'),
    ('label2', 'Label Two')

)

class Quiz(models.Model):
    label = models.CharField(blank=True, max_length=400)
    slug = models.SlugField()

    def __unicode__(self):
        return self.label

class QuizForm(ModelForm):
    # Change the 'label' widget to a select box.
    label = forms.CharField(widget=forms.Select(choices=CHOICES_LABEL))

    class Meta:
       # This tells django to get attributes from the Quiz model
       model=Quiz

Next, in your views.py you might have something like this:

from django.shortcuts import render_to_response
from forms import *
import my_quiz_model

def displayQuizForm(request, *args, **kwargs):
   if request.method == 'GET':
       # Create an empty Quiz object. 
       # Alternately you can run a query to edit an existing object.

       quiz = Quiz()
       form = QuizForm(instance=Quiz)
       # Render the template and pass the form object along to it.
       return render_to_response('form_template.html',{'form': form})

   elif request.method == 'POST' and request.POST.get('action') == 'Save':
       form = Quiz(request.POST, instance=account)
       form.save()
       return HttpResponseRedirect("http://example.com/myapp/confirmsave")

Finally your template would look like this:

<html>
  <title>My Quiz Form</title>
  <body>

  <form id="form" method="post" action=".">

   <ul>
    {{ form.as_ul }}
   </ul>

   <input type="submit" name="action" value="Save">
   <input type="submit" name="action" value="Cancel">
  </form>

  </body>
</html>
Luis
I get part of this. What I don't get is how to display the questions and choices as part of a quiz. This doesn't seem to cover that, unless I'm just misunderstanding. Won't this just display a quiz with preset choices?
f4nt
I think this site will help you figure things out: http://djangobook.com/en/1.0/chapter05/ and http://djangobook.com/en/1.0/chapter07/
Luis
+3  A: 

Yeah I have to agree the documentation and examples are really lacking here. The is no out of the box solution for the case you are describing because it goes three layers deep: quiz->question->answer.

Django has model inline formsets which solve the problem for two layers deep. What you will need to do to generate the form you want is:

  1. Load up a quiz form (just a label text box from your model)
  2. Load a an question formset: QuestionFormSet(queryset=Question.objects.filter(quiz=quiz))
  3. For each question load up a answer formset in much the same way you load up the question formset
  4. Make sure you save everything in the right order: quiz->question->answer, since each lower level needs the foreign key of the item above it
Jason Christa
+3  A: 

Curiously enough, after reading this question yesterday I stumbled upon a Django article explaining how to do exactly what you want with the exact same Quiz/Question/Answer models. Check it out here. I am pretty sure that should get you on your way.

Paolo Bergantino
That's almost creepy... Thanks!
f4nt
No problem. As soon as I read the article I was like "wasn't there a question in Stackoverflow asking EXACTLY THIS?!"
Paolo Bergantino
I actually found a newer article on the same website that has a more up-to-date Django way of achieving what you want. Check out the new link in my answer for this.
Paolo Bergantino