Ok, ich habe eine Lösung gefunden, die nicht ajax überhaupt verwenden und scheint nett genug, um mich:
Erstellen Sie so viele Formulare wie nötig und machen Sie sie zu Unterklassen. Fügen Sie in das erste Formular ein verstecktes Integer-Feld ein:
class Form1(forms.Form):
_nextstep = forms.IntegerField(initial = 0, widget = forms.HiddenInput())
foo11 = forms.IntegerField(label = u'First field of the first form')
foo12 = forms.IntegerField(label = u'Second field of the first form')
class Form2(Form1):
foo21 = forms.CharField(label = u'First field of the second form')
class Form3(Form2):
foo31 = forms.ChoiceField([],
label=u'A choice field which choices will be completed\
depending on the previous forms')
foo32 = forms.IntegerField(label = u'A last one')
# You can alter your fields depending on the data.
# Example follows for the foo31 choice field
def __init__(self, *args, **kwargs):
if self.data and self.data.has_key('foo12'):
self.fields['foo31'].choices = ['make','a','nice','list',
'and you can','use your models']
Ok, das war für die Formulare, hier ist die Ansicht:
def myview(request):
errors = []
# define the forms used :
steps = [Form1,Form2,Form3]
if request.method != 'POST':
# The first call will use the first form :
form = steps[0]()
else:
step = 0
if request.POST.has_key('_nextstep'):
step = int(request.POST['_nextstep'])
# Fetch the form class corresponding to this step
# and instantiate the form
klass = steps[step]
form = klass(request.POST)
if form.is_valid():
# If the form is valid, increment the step
# and use the new class to create the form
# that will be displayed
data = form.cleaned_data
data['_nextstep'] = min(step + 1, len(steps) - 1)
klass = steps[data['_nextstep']]
form = klass(data)
else:
errors.append(form.errors)
return render_to_response(
'template.html',
{'form':form,'errors':errors},
context_instance = RequestContext(request))
Das einzige Problem, das ich gesehen habe, ist, dass bei Verwendung von {{form}} in der Vorlage form.errors aufgerufen wird und somit das neue Formular (z. B. Form2) automatisch mit den Daten des vorherigen Formulars (Form1) validiert wird. Ich iteriere also über die Elemente im Formular und verwende nur {{item.id}}, {{item.label}} und {{item}}. Da ich die Fehler des vorherigen Formulars bereits in der Ansicht abgerufen und an die Vorlage übergeben habe, füge ich ein Div hinzu, um sie oben auf der Seite anzuzeigen.