Search code examples
djangodjango-formsdjango-formwizard

Formwizard with custom queryset


I have a problem with formwizard. In step 3 of the wizard I use a filtered query which depends on choices from step 1 and 2. My wizard works fine when moving forward, but when a user presses previous, or changes the choices of step 1 and 2, things go wrong (validation error or filters won't work).

Here is my forms.py:

class BoekForm3(forms.Form):
    Activiteit = forms.ModelChoiceField(queryset=Activiteit.objects.all(), empty_label="(Nothing)")

If I use queryset Activiteit.objects.none() in forms.py the correct fields in step3 of the wizard show up right, but the step3 always give a validation error.

If I use queryset Activiteit.object.all() in forms.py the correct (filtered) fields show up in step3 when going forward, and the form validates. However when a user presses previous in step4 the filter is gone, and all choices are available.

Edit2: ok I found out that get_form is read every time (removed my previous edit about this). The problem with my code is that when a user goes back from step4 to step3, the step get_form is using, is step4. I tried to change:

"if step == 'step3'"

into:

"if step == 'step3' or step == 'step4':"

in my view, but this results in a key error on Activiteit

I think that the fields are updated moving to step3, but the form isn't. I have included my views.py below.

class BoekingWizard(SessionWizardView):
    def get_template_names(self):
        return [TEMPLATES[self.steps.current]]

    def get_context_data(self, form, **kwargs):
        plaatjes = Activiteitsgroepen.objects.all()
        context = super(BoekingWizard, self).get_context_data(form=form, **kwargs)
        if self.steps.current == 'step1':
            context.update({'plaatjes': plaatjes})
        return context

    def get_form(self, step=None, data=None, files=None):
        form = super(BoekingWizard, self).get_form(step, data, files)
        if step == 'step3':
            x = self.get_cleaned_data_for_step('step1') or {}
            filter1 = x['Type_activiteit'].Groep
            y = self.get_cleaned_data_for_step('step2') or {}
            if y['Aantal_personen'] < 76:
                filter2 = 'kleinere groepen'
            elif y['Aantal_personen'] > 76:
                filter2 = 'grotere groepen'
            else:
                filter2 = 'geen selectie'
            reeks = ['1','2','3']
            if y['Dagdeel'] in reeks:
                filter3 = 'Dagdeel'
            elif y['Dagdeel'] == '4':
                filter3 = 'Hele dag'
            elif y['Dagdeel'] == '5':
                filter3 = 'Middag + Avond'
            elif y['Dagdeel'] == '6':
                filter3 = 'Dag + Avond'
            form.fields['Activiteit'].queryset = Activiteit.objects.filter(Soort__Groep = filter1).filter(Grootte__Naam = filter2).filter(Dag__Omschrijving = filter3)
        return form

Solution

  • It looks more and more that Formwizard doesn't support what I want. I therefore started to work with normal forms, and store the cleaned_data in a session. The advantage is that I have more control, and I know better what is going on. Here the the idea:

    def BoekingForm(request):
        if request.method == 'POST':
            if request.POST.get('BoekForm2'):
                form1 = BoekForm1(request.POST)
                if form1.is_valid():
                    request.session['Data_BoekForm1'] = form1.cleaned_data
                    if 'Data_BoekForm2' in request.session:
                        x = request.session['Data_BoekForm2']
                    else:
                        x = None
                    form2 = BoekForm2(initial = x)
                    return render_to_response('boeking/form2', {
                        'form2': form2,
                    }, context_instance = RequestContext(request))
    
            else:
                    return render_to_response('boeking/form1', {
                        'form1': form1,
                    }, context_instance = RequestContext(request))
            if request.POST.get('BoekForm3'):
                form2 = BoekForm2(request.POST)
    

    Unless somebody comes with a solution the solve my question within Formwizard, I will have to mark my own answer as the solution.