[Ann] emulateRedirect: emulates redirection inside Zope
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. Presenting the form without redirection is possible but has several caveats: Side effects caused before the problem has been detected are difficult to discard. The 'base' used by the browser for URL resolution may become wrong, seriously confusing the browser and/or Zope. The small External Method 'emulateRedirect' emulates a redirect without an extra interaction with the browser. It resets the REQUEST parameters such that they get the same values as for a direct traversal to the redirected object. Furthermore, it sets the 'base' tag used by the browser for resolution of relative URL such that relative references from the redirected to object become correct. 'emulateRedirect' provides control over the transaction ('abort', 'commit', 'keep'). 'emulateRedirect' works for Zope 2.3. It may work with Zope 2.2. As it uses undocumented Zope publishing features, it may break with any new Zope version. More information and download via: URL:http://www.dieter.handshake.de/pyprojects/zope Dieter
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. 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. Can anybody comment whether this or the "emulateRedirect" approach is better? Joachim
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. Dieter
participants (2)
-
Dieter Maurer -
Joachim Werner