[Zope] [Ann] emulateRedirect: emulates redirection inside Zope

Dieter Maurer dieter@handshake.de
Wed, 2 May 2001 22:39:16 +0200 (CEST)

Joachim Werner writes:
 > > Dieter Maurer writes:
 > > The common task:
 > >
 > >      A user fills a form and submits it. The submitted data is checked
 > >      and if problems are detected, the user gets its
 > >      original form together with a problem indication
 > >      *AND* his already filled in data.
 > >
 > > is not yet well supported.
 > >
 > > A redirection to the form suffers from browser differences
 > > in the handling of the old request data and
 > > the difficulty to add all of them into the redirected
 > > URL.
 > I always used an approach like this (only works with some session management
 > to get persistence of course):
 > This is a pure example, so don't look at the details ;-)
 > In the form I have:
 > <dtml-if something_submitted>
 > *** check the data here, display the errors if necessary; if no errors, save
 > the data and redirect to the thankyou page
 > </dtml-if>
 > <form ...>
 >  *** in the form, the variables are all called from the session ("<dtml-var
 > variable missing>" to make sure there is no error if it was empty)
 > </form>
 > I call the form in the action method (by just not specifying an action). So
 > there is a loop until everything is fine.
An interesting approach!

You do not even need a session for this.

It has one drawback for the application in my mind:

  I am working on an EnhancedPropertyManager:

    This object manages a sequence of attributes, each
    attribute with associated rights and an optional validator.

    Of course, a single form action should be able to update
    several property managers.
    To preserve modularity,
    I do not want to separate the check from the action.
    Thus, I want to tell each property manager, look these
    are the updates I have for you. It gets a problem handler
    instance where it can record each problem it encounters.
    When all managers are updated, I look at the problem handler
    whether it has any problem. If not, fine.
    If it has, however, I have an inconsistent state,
    the transaction needs to be aborted and the user informed
    about all problems.

  If I have a session object, I can achieve this without
  the "emulateRedirect" and use a standard "raise 'Redirect'".

  I do not like it very much to have to put the REQUEST.form
  content into the correct slot of a session object.
  In another project, we use a special product, called
  "FormDispatcher" for this purpose. It automatically
  remembers the form content when the form is left
  and restores it on return. Unfortunately, colleagues
  have some problems with the tool. I hope, "emulateRedirect"
  is easier.

 > One could also do the same by
 > redirecting back to the form if there is an error found by the action
 > method. As long as the fields are prefilled by Zope, I don't think the
 > browser issue applies.
That's where the session object comes in. It's needed such that
Zope is able to prefill the fields. And, of course, the session
objects needs to have been filled with users input before.

Now, the session content behaves like global variables.
One needs to carefully manage their use to avoid use of them
in the wrong context: possible but a bit error prone.

 > Can anybody comment whether this or the "emulateRedirect" approach is
 > better?
The "emulateRedirect" has 2 drawbacks:

  1. It uses undocumented Zope internas that may change without
     warning in new versions.

     You may not want to use such code in a production environment.

     Now, the complete code is about 10 lines. With a bit
     of Python knowledge, you may trust yourself to fix
     it easily if it should break....

  2. The method changes Zope internal view as if a redirect
     had been performed, but, of course, the browser
     (and intermediate HTTP processing agents) do still
     think of the original URL. They might get confused.
     Setting the "base" tag to avoid this, but there
     may be situations where this is not enough.