On Nov 6, 5:36 pm, txranger <txran...@gmail.com> wrote:
> yes this is very similiar to what I am working on right now. Being a
> newbie it seems much harder than it should be. I ended up setting a
> state variable within self.extra_context. It is set by overriding the
> process_step function in the FormWizard class based on the results of
> the previous forms values.  This state variable is also used in the
> get_template function(also overridden) to control which template is
> displayed.
>
> In my case I have 10 forms/sections and the quickest way through will
> show 6 of them and the longest will show 9 forms.
>
> When you say  " Form2 (must be dynamically set based on the submitted
> values in Form1)"  do you mean which form or which fields within that
> form?
>
> I am currently struggling with the display of pending changes and if
> the user does not like them allowing them to go back and change them
> so any ideas or solutions would be appreciated.
>
> txranger
>
> On Nov 3, 1:30 pm, "Mark L." <mark.l...@gmail.com> wrote:
>
> > Just to sparkle your imagination, the desired workflow of aFormWizard
> > I am trying to implement is as follows: Form1 -> Form2 (must be
> > dynamically set based on the submitted values in Form1) -> Form3 (show
> > a preview of pending changes to the user) -> done() (apply the
> > changes). I know, it sounds a bit complicated, but that is the way it
> > *has* to be.


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
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to