Often, you want to leave a form but come back later with the already filled in values intact.
This happens, e.g., for form validation. When the validation fails, you will want to redisplay the form together with an appropriate error indication. An alternative here would be to put the validation code in the form itself and ensure, it is not activated for the first form entry (you could use a hidden variable for this purpose).
Another case are forms with complex input entries which require special support to be filled. When you leave the form to get this support, the form values provided so far must be saved in order to be available later, when you come back with the new value for the complex entry.
The dispatcher provides uniform support for these use cases. It controls a form and manages the form data for it. This includes initialization, saving data in a session object, dispatching to various destinations and restoring the saved values, when the form is reentered. Furthermore, it avoids problems with HTML checkbox and multiple selection handling.
A form dispatcher is used to manage the variables of a form. It
provides services for form initialization, form update and the
dispatch out of the form to various form actions. During dispatch,
the current form values are saved in a session object. When the
form is updated, the data is put back into
REQUEST.form and updated with the new values provided
by update.
A form dispatcher works with (at least) the following objects:
the id of the form controlled by the dispatcher
The dispatcher calls this object like a DTML method (or through
mapply) after REQUEST.form and
REQUEST.other have been set up.
The default is Client.
the description of the managed form fields.
The dispatcher calls this object like a DTML method. The call should return either a list of form value descriptions or a dictionary thereof. Each description is a dictionary describing various aspects managed by the dispatcher.
The default is ClientDescription
the id of a session managing object.
This object is used to save the current form values during dispatch.
The default is FSSession.
the key to use for saving the current form values in the session object.
The default is the dispatchers physical path.
The form dispatcher supports the following use cases:
newthe form is used to create a new object.
The initial values of form variables are not taken from the
environment unless the form description contains an explicit
init or fixed description to this effect.
Other form variables are empty (depending on
dtype).
editthe form is used to edit an existing object.
Most form variable values are taken from the environment. Only
fixed values are taken from the description.
showrender with currently remembered values.
This method is used, when the Dispatcher is part or a larger context, e.g. a Wizzard. This context has performed global initialization or updates and then selectively calls for rendering of a dispatcher.
clearthe form values are reset to empty (depending on
dtype). Only fixed values are not
changed.
the form is left with the intention to come back with new or changed values. The current form values are saved in the session object to be restored lated when we come back.
updateupdate the form after a dispatch.
The original form values are restored from the session object.
They can be overridden or completed by additional values provided
in the update call.
The only anticipated event sequences are:
(new | edit) (clear | show | dispatch update)* leave?
Client__the id of the form controlled by the dispatcher
The default is Client.
ClientDescription__the id of a method returning a dictionary or list that describes the form variables.
The default is ClientDescription.
Each variable is described by a dictionary. The following keys are interpreted. There may be more, used for other purposes:
namethe variable name
initan initial value for new calls.
This is either None or a value. None
means, use from the environment (if present). A missing
init is equivalent to the type specific empty
value.
fixedthe value is not changed by clear or
__call__
This is either None or a value. None
means, use from the environment (if present).
If fixed is not present, then clear
resets the variable to the type specific empty value.
permanentthe value is not changed by update.
This should be a truth value, the default is 0.
It is usually used together with fixed variables to
prevent modification by update.
It currently only affects update. It might be more
intuitive, if permanent would imply
fixed.
dtypethe variables data type (used to determine empty values)
Must be either string, int,
list or tuple. Defaults to
string.
SessionObject__the id of the session object used to remember the values
The default is FSSession.
It is expected, that the session object has get and
set methods to retrieve and set session data.
SessionKey__the saved values are collected in a dictionary and saved under this key.
The default is the physical path of the dispatcher.
If the value is *dynamic*, then the session key is
dynamically computed form the physical path. This is necessary, if
the dispatcher is used as part of a ZClass.
initializeSession__the id of a method that initialized the session.
The default is initializeSession.
FSSession requires that the session is initialized
precisely once in each request that uses the session. Initializing
more than once may lead to loss of data. Not initializing may lead
to exceptions, let the application work with stale data and does
not save modifications. It is expected that
initializeSession is idempotent, i.e. can be called
repeatedly in a single request without advertant effects.
For some session types (unlike FSSession), no explicit session
initialization may be required. In such a case,
initializeSession__ may be deleted.
newfill a new form (mostly empty).
All variables get their initialization/fixed values (if
defined). Other variables get the dtype specific empty
value.
The values are placed in REQUEST and
REQUEST.form.
None values for init or
fixed are resolved from the environment.
The special value edit__=0 is defined.
The method is called either directly from the Web or from DTML, to better control the environment.
Arguments: DTML-like
editfill a form for editing (mostly filled).
All variables get their values from the environment with the
exception of fixed variables. They get the specified
value, unless the value is None.
The values are placed in REQUEST and
REQUEST.form.
The special value edit__=1 is defined.
The method is usually called from DTML which sets up the environment.
Arguments: DTML-like
updateupdate the remembered values and render the client.
The variables are filled with their remembered values. New
values from update override pervious values, unless
errors__ has a true value. In this latter case, no
values are overridden. In no case, update overrides a
variable declared as permanent.
Usually, the update values are taken from the environment. If,
however, values__ is defined, then its value must be a
mapping and it, alone, is used for updating. The namespace is not
relevant in this case.
The values are placed in REQUEST and
REQUEST.form.
update restores the base URL, remembered during the
last dispatch. This is in order to counter the lengthening URL
problem that is favoured by Zopes acquisition.
The method is usually called from DTML. It may, however, also be called directly from the Web.
update accepts DTML-like arguments. However,
errors__ and values__ are treated
specially.
If errors__ is defined and has a true value, the
old values are simply restored. No values are overridden by the
update.
If values__ is defined, then (with the exception of
errors__), the environment is irrelevant. Only
values__ (which must be a mapping) defines values to
override remembered values. This provides for precise control over
the overridden values.
__call__remember the current values in the session object (with the
exception of fixed variables) and dispatch to a new
destination.
If the environment does not contain a value for a variable which
is not fixed, then the empty value is used. This is
necessary for checkboxes and multiple selections to work
correctly.
The values and the base URL are saved in the session object for
later restoration by update.
To determine the destination, __call__ looks for a
variable of the form (.*)__disp(.[xy])?. It takes the
part match by (.*) as the destination.
If the destination contains ?, it is split at it.
The first part becomes the destination, the second part is decoded
as a query string and the corresponding parameters placed into
REQUEST and REQUEST.form.
The destination may be an URL path.
restrictedTraverse is used to find the actual
destination.
If no destination can be found, the client is simply rendered
(equivalent to show). This is useful to have shorter
URLs. Currently, the same happens, when REQUEST does
not have a form attribute. However, this may change in
the future.
The method is usually called only from the Web.
Arguments: dtml-like
clearclear (make empty) non-fixed fields and render the client.
Arguments: DTML-like
showrender the client.
Arguments: DTML-like
getValuesreturn a mapping object containing the saved values.
This is the mapping saved in the session object. Writing to it changes the session maintained information.
Arguments: none
Most methods support DTML-like arguments. This means, there are
two optional positional arguments client and
REQUEST and arbitrary keyword arguments. Unlike
DTML-objects, the default value for client is the
dispatcher object. REQUEST may be a mapping or a DTML
namespace.
The methods construct a DTML namespace from this in the same
way, DTML objects do. When an object is rendered, the
render method of this namespace is used.
Usually, new, edit,
clear, and show render the client. If,
however, DispatcherDoNotRender__ is true, rendering
and REQUEST modification are suppressed. This allows
e.g. a Wizzard to call these methods just to change the remembered
values.
For a DTML object or when the object is not acquisition wrapped
or when the namespace is bound, the namespace's render
method is used for rendering. Other objects are rendered through
ZPublisher.mapply.mapply.
Zopes acquisition and the possibility to call methods both via
HTTP and directly can lead to great confusion with respect to base
URLs. The base URL is essential for the resolution of any relative
URL in an HTML page. The Dispatcher tries to counter this confusion
by explicitly setting the HTML base element. For this purpose, it
must find out its own URL. Note, that it can not use
absolute_url, as this method discards any context. For
new, edit, clear,
show and __call__, the dispatcher assumes
that it was activated directly by HTTP and that it can use
REQUEST.URL1 or REQUEST.URL0,
respectively. If this assumption is wrong, the caller can define
DispatcherURL__. It should be the URL of the
dispatcher object. If the client is rendered at the end of an
update, the dispatcher restores the remembered base
URL.
Note that the URL/BASE request variables are fixed for the rendering as well. They reflect the true client/destination information, not that of the dispatcher. Other request variables are not changed. This may change in the future.
Download the Dispatcher TGZ archive
and unpack it into your Zope Products folder. Restart
Zope. You should then find a Form Dispatcher entry in
your add-list.
This product is covered by a Python-like open source license. For details, see the Copyright notice at the top of Dispatcher.py.
render. This allows to use Python Scripts with
namespace binding to be used as client and to pass parameters to it
via the namespace. Note, that this is not necessary in general, as
all dispatcher variables go through REQUEST
anyway.__call__ to behave like
show, if no destination can be found.mapply rendering is used for destinations which are
not DTML or unwrapped objects. This allows to pass parameters to
Python Scripts, even if they do not bind the namespace (which is
really dangerous), and to External Methods. A future implementation
should probably use the DTML render, if the target
object uses namespace binding.