Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Keeping state in the FormWizard: instance attributes considered harmful?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  3 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Mark L.  
View profile  
 More options Nov 3, 2:30 pm
From: "Mark L." <mark.l...@gmail.com>
Date: Tue, 3 Nov 2009 11:30:42 -0800 (PST)
Local: Tues, Nov 3 2009 2:30 pm
Subject: Keeping state in the FormWizard: instance attributes considered harmful?
Since FormWizard is instantiated only once (in the urlconf, as
proposed in the documentation), no assumptions can be made about the
integrity and validity of its instance methods/attributes. It is very
easy to run into a situation, when self.form_list is altered and not
restored to a value, with which the FormWizard was initialized.
self.extra_context is also available at all times and doesn't get
cleaned up.

The question is, how to store the state inside the step and between
the steps?

For intra-step state (for example, if I want to set something in
parse_params and then access it in process_step) it seems rather
trivial, - just set an instance attribute and unset it later. This is,
however, not safe, because if something goes wrong during the
__call__, that attribute will not get unset. Nevertheless, it is not
so hard to implement, I guess.

What about inter-step state, though? I don't see an easy way to do it.
At first, I thought, that instance attributes are ok to use for this,
but then I've of course realized, that once FormWizard is initialized
in the urlconf, there will be only one of it, ever (__call__ will get
called, but that's it - there will be only once instance).

One possible way to work with it is sessions, but they have their own
limitations, - you cannot store unpicklable objects in them (so you
can't store a model or a curried function inside a session, right?). I
guess, this is all I can think of right now.

Just to sparkle your imagination, the desired workflow of a FormWizard
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.

Obviously, the best way to work with it would be actually generating
the resultant changes as curried functions with attached descriptions,
that can be shown to the user, somehow pass them between the steps and
then actually call those functions in done(). This, however, seems
impossible to implement.

I'd be most grateful, if someone could give me an idea or two or, at
least, point me into a right direction.

Mark


    Reply    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
txranger  
View profile  
 More options Nov 6, 9:36 am
From: txranger <txran...@gmail.com>
Date: Fri, 6 Nov 2009 06:36:02 -0800 (PST)
Local: Fri, Nov 6 2009 9:36 am
Subject: Re: Keeping state in the FormWizard: instance attributes considered harmful?
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:


    Reply    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark L.  
View profile  
 More options Nov 7, 5:14 am
From: "Mark L." <mark.l...@gmail.com>
Date: Sat, 7 Nov 2009 02:14:39 -0800 (PST)
Local: Sat, Nov 7 2009 5:14 am
Subject: Re: Keeping state in the FormWizard: instance attributes considered harmful?

On Nov 6, 5:36 pm, txranger <txran...@gmail.com> wrote:

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


    Reply    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google