Download FSSession.tgz and untar it in your root Zope directory. Create a directory called FSSession in the var directory , give it the appropriate permissions and restart Zope.
Create an FSSession instance somewhere in your Zope tree where session support is required. The instance will be named FSSession. To use you must first call:
<dtml-call FSSession>
preferably from your standard_html_header or any other object that has access to FSSession. This will initialize the Session object and register it with Zope's transaction manager.
The FSSession object behaves like a python dictionary and it supports all dictionary methods apart from copy, which I think is not applicable in this context. The keys and values of FSSession can be any picklable object, which includes most python objects. See the python library reference for more details about picklable objects. It has the following additional methods:
Assuming that you have already made a call to FSSession (for instance in your standard_html_header).
Set a simple session variable:
<dtml-call "FSSession.set('name','donkey')">
Or a more complex one:
<dtml-call "FSSession.set('expensivemethod',expensivemethod())">
If expensivemethod returns a list you can then retrieve it in a future session by:
<dtml-in "FSSession['expensivemethod']"> <dtml-var sequence-item> </dtml-in>
To create an integer session variable counter which keeps track of how many times a particular user accesses a given page:
<dtml-if "FSSession.has_key('counter')"> <dtml-call "FSSession.set('counter',FSSession['counter']+1)"> <dtml-else> <dtml-call "FSSession.set('counter',1)"> </dtml-if>
To view the session contents:
<dtml-var "_.str(FSSession)">
or directly by using the showSession.py utility:
python utilities/showSession.py var/FSSession/<path to session file>
A call to:
<dtml-var "FSSession.url('http://www.bigdonkey.com/client1)">
will return:
http://www.bigdonkey.com/client1?SessionUID=<sessionuid>
if the client has cookies disabled, or:
http://www.bigdonkey.com/client1
if they are enabled.
To iterate over all session keys:
<dtml-in "FSSession.keys()"> ... </dtml-in>
This is a more complete usage example on how to make input forms sticky. When a client fills up a form, usually we need to process the entries, collect any error information and redirect the client back to the form without loosing the valid entries. Here is an approach based on FSSession:
sticky
<dtml-var standard_html_header> <dtml-call FSSession> <!-- you can add the above call inside standard_html_header--> <dtml-unless "FSSession.has_key('register_form')"> <dtml-call "FSSession.set('register_form',{})"> </dtml-unless> <!-- Checks if Session object has an entry for this form. If not create a new one --> <H2>Registration</H2> <dtml-if "FSSession.has_key('error_list')"> <dtml-if "_.len(FSSession['error_list'])!=0"> <P><FONT SIZE=+2 COLOR='red'>ERROR IN FORM</FONT> <P>The following fields had errors. Please correct and click the submit button. <UL> <dtml-in "FSSession['error_list']"> <LI><dtml-var sequence-item> </dtml-in> </UL> </dtml-if> <dtml-else> <P>Fill in this form to submit a registration request. The request will be processed and upon approval your account will be created and you will be notified via email. </dtml-if> <FORM ACTION="addUser" method=post> <TABLE> <TR> <TD ALIGN="LEFT" VALIGN="TOP"> <STRONG>Login Name</STRONG> </TD> <TD ALIGN="LEFT" VALIGN="TOP"> <INPUT TYPE="TEXT" NAME="username" VALUE="<dtml-var "FSSession['register_form'].get('username','')">" SIZE="50"> </TD> </TR> <!-- Uses the get dictionary method with a default argument. If the key is not found then the default argument is returned, in this case an empty string. Alternatively one could have inserted the form contents into the namespace by using: <dtml-with "FSSession['register_form']" mapping> and access the contents like: &dtml-name; or <dtml-var name> but in case the attribute was undefined an exception would be raised. --> <TR> <TD ALIGN="LEFT" VALIGN="TOP"> <STRONG>Password</STRONG> </TD> <TD ALIGN="LEFT" VALIGN="TOP"> <INPUT TYPE="PASSWORD" NAME="password" SIZE="50"> </TD> </TR> <TR> <TD ALIGN="LEFT" VALIGN="TOP"> <STRONG>Retype Password</STRONG> </TD> <TD ALIGN="LEFT" VALIGN="TOP"> <INPUT TYPE="PASSWORD" NAME="password2" SIZE="50"> </TD> </TR> </TABLE> </FORM> <dtml-var standard_html_footer>
<dtml-var standard_html_header> <dtml-call FSSession> <dtml-call "FSSession['register_form'].update(REQUEST.form)"> <dtml-call "FSSession.set('error_list',[])"> <!-- Add the form data in session object and initialize an error list--> <dtml-if "password!=password2 or password==''"> <dtml-call "FSSession['error_list'].append('Password- Passwords do not much or empty')"> </dtml-if> <!-- some simple error checking--> <dtml-if "_.len(FSSession['error_list'])!=0"> <dtml-call "RESPONSE.redirect('register')"> <dtml-else> ... register user ... <dtml-call "FSSession.delete('error_list')"> <P>Thanks for registering with us. You will shortly receive an email with more details. </dtml-if> <dtml-var standard_html_footer>
Each session stores its data in an individual file under the var/FSSession directory based on initial creation time. A busy site will quickly create thousands of files and to increase performance the files are distributed in a three level directory hierarchy. The first corresponds to the day of the year (1-365) the second to the hour (0-23) and the third to the minute (0-59). Under the minute directory the session data are stored in files with the sessionUID as the filename. This scheme makes it easy to delete old session data by running a cron job at the required interval and deleting the appropriate entries. You can view the session data directly by using the showSession.py utility in the utilities directory (see Examples).