Complex Formsets

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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 %}

More like this

  1. Complex Formsets, Redux by smagala 4 years, 1 month ago
  2. Complex Form Preview by smagala 5 years ago
  3. Dynamically adding forms to a formset with jQuery by elo80ka 5 years ago
  4. Semi-Portable recaptcha integration with django forms by pinkeen 3 years, 4 months ago
  5. i18n base model for translatable content by foxbunny 5 years, 9 months ago

Comments

matrix (on April 2, 2009):

Could you give a example of the QuizForm and QuestionForm used.

Thanks

#

smagala (on June 3, 2009):

@matrix - check out the two links in the sidebar description. I used Malcolm's code from his first link as the starting point for my code.

It is worth noting that I've switched to using code that is nearly identical to Malcolm's second post - it's a bit cleaner than mine. Malcolm has posted a full working example in that second link.

#

kramed (on November 23, 2009):

Can you please make a snippet using the new way you found? (The guys link has been dead the past few days)

#

(Forgotten your password?)