forms.py ======== from django.forms.formsets import BaseFormSet, formset_factory, ValidationError class BaseDynamicFormSet(BaseFormSet): def __init__(self, data=None, *args, **kwargs): self.extra=0 super(BaseDynamicFormSet, self).__init__(*args, **kwargs) if data: # code based on django.forms.formsets.py # BaseFormSet __init__ self.data = data self.is_bound = True self.management_form.data = data self.management_form.is_bound = True if self.management_form.is_valid(): self._total_form_count = \ self.management_form.cleaned_data['TOTAL_FORMS'] self._initial_form_count = \ self.management_form.cleaned_data['INITIAL_FORMS'] else: raise ValidationError( 'ManagementForm data is missing or has been tampered with') def _defered_init(self): self.management_form.initial['TOTAL_FORMS'] = len(self.forms) class BaseQuizDynamicFormSet(BaseDynamicFormSet): def __init__(self, quiz, *args, **kwargs): super(BaseQuizDynamicFormSet, self).__init__(*args, **kwargs) self.add_forms(quiz) super(BaseQuizDynamicFormSet, self)._defered_init() def add_forms(self, quiz_id): # Malcolm's create_quiz_forms logic now goes here questions = Question.objects.filter(quiz__pk=quiz_id).order_by('id') for pos, question in enumerate(questions): prefix = '%s-%s' % (self.prefix, pos) form = QuestionForm(question, self.data, prefix=prefix) self.forms.append(form) if not self.forms: raise Http404('Invalid quiz id.') QuizFormSet = formset_factory( QuizForm, formset=BaseQuizDynamicFormSet) views.py ======== def quiz_form(request, quiz_id): if request.method == 'POST': formset = QuizFormSet(quiz_id, data=request.POST) answers = [] if formset.is_valid(): for form in formset.forms: answers.append(str(int(form.is_correct()))) return HttpResponseRedirect('%s?a=%s' % (reverse('result-display',args=[quiz_id]), ''.join(answers))) else: formset = QuizFormSet(quiz_id) return render_to_response('quiz.html', locals()) template ======== Just change this: {% for form in forms %} to this: {% for form in formset.forms %}