Hello
To be honest, I've spent quite a time messing around with FormWizard
(especially, since I was using it wrong at first).
Do remember, that extra_context also persists between requests (which
is bad and can _not_ be depended upon). The thing is, you can set any
instance attributes and they *will* persist between the requests,
pointing to the same instance of the wizard. This, however, seems to
be extremely unsafe and not a good thing to do at all, because you
have no way of knowing which particular request set an attribute. In
short - don't try it.
What I've ended up doing is the following: I've stopped instantiating
the wizard in urlconf (as suggested by the examples in the dev
documentation), but instead I make sure, that the wizard is
instantiated on every request by wrapping it in a simple "view"
function and then using that function in the urlconf. The function
looks literally like this:
def my_wizard(request, *args, **kwargs):
wiz = MyWizard([Form1, Form2, ... FormN])
# where FormX are my form classes
return wiz(request, *args, **kwargs)
A wizard's __call__ method is just like any other view function, - it
takes a request and other arguments and returns a response. So it will
work perfectly, while ensuring, that you start with a clean plate on
every request.
When I say "Form2 must be dynamically set.. etc", means Form2 must be
of a different form class (it is a ModelForm autogenerated from a
Model, so it makes no sense to mess with the fields). It can be
handled in process_step by altering self.form_list, I've already
figured that one out.
As for displaying pending changes, I do it like this. Presumably,
there is a number of "actions" to be performed based on the submitted
data in the forms, right? Those "actions" are, basically, functions,
that need to be run in done(), right? You can associate each of that
"action" with a "description", that can be displayed in the last form
(the "Confirmation form"). In my case, the "actions" are represented
by self-contained ("curried") functions. You, basically, keep a list
of tuples where the first element of the tuple is a description of an
action and the second element is that action itself.
So in the last form's handler you do something like this:
if step == last_step:
self.extra_context['actions'] = [act[0] for act in self.actions]
# so that you have access to the descriptions in the template
def done(self):
for action in [act[1] for act in self.actions]:
action()
return HttpResponseRedirect('/done/')
Or something like that.
Another option would be using sessions to store state data, but this
is complicated by the fact, that only picklable objects can be stored
in the session. And you have to worry about clearing the state at the
appropriate time as well. I haven't explored this possibility yet.
Hope that helped
Mark