• BU Home | 
  • News | 
  • Events | 
  •  | 
  •  

Web Services Wiki

Welcome Guest: Login

Standard Setting: Preload Hook Script

Under some circumstances you want to preload form fields with data.  Some example uses of this would be to:

  1. If users need to authenticate to view the form, looking up information about them by their username (e.g. first, last names, address, phone number), preloading that information and set those preloaded form fields to readonly.  In this way their information can be guaranteed valid.
  2. Feeding a query to the form (e.g. a row id from a database table) and preloading the form with that information.  This could be part of a larger database-driven application built in silva using forms and code sources.
  3. Preload a date field with todays date.

When Tropos fields are publically rendered, they always check REQUEST for a key with the same name as the field id.  If this exists, Tropos uses this key's value as the value for the field.  This behavior allows us to 'preload' form fields.

Standard "Authenticated User" Preload Hook

The most common use of a preload hook is to pre-fill information for the currently authenticated user.  This is a standard preload hook, and is labeled 'Personal Info for current user'.  This hook will preload the name, email, bethelid, username, po, home (mailing) address and the current date.  In order for the preload to work, the fields in the form have to be named appropriately:

Last Name, e.g. "Smith" lname
First Name, e.g. "Johnny"* fname
Legal First Name, e.g. "John"* legal_fname
Middle Name, e.g. "Quincy"* mname
Legal Middle Name, e.g. "Quincy"* legal_mname
Full Name, e.g. "Johnny Smith"* fullname
Preferred Bethel Email Address, e.g. "john-smith@bethel.edu"
email
Bethel ID, e.g. 0123456
bethelid
BCA/NetID, e.g. jsmith
username
Bethel PO Number, e.g. 1234
bethel_po
Home Address, Street 1
home_street1
Home Address, Street 2
home_street2
 Home Address, Street 1 & 2 combined home_street_comb
Home Address, City
home_city
Home Address, State
home_state
Home Address, Zip
home_zip
The current date
date

*The legal first name, legal middle name, and last name contain the legal name of the currently authenticated user.  The first name, middle name, and full name will contain different data depending on the user's preferred name. 

If the user has a preferred name stored, then the first name will contain their preferred name and the middle name will be empty.  Likewise the full name will contain the preferred first name and the last name. 

If the user has no preferred name stored, then the first name will contain the same data as the legal first name and the middle name will contain the same data as the legal middle name.  The full name will contain the legal first name and the last name (no middle name).

Initial Setup

Preload hooks are Python Scripts (well, they can be any callable ZMI object, really).  Tropos looks in the nearest folder (zope Folder, not Silva Folder) with id 'source' for these scripts.  So, create a folder with name 'source' to place your preload script in.  Note: other tropos features use this 'source' folder as well.  Tropos uses acquisition (not absolute path) to find the source folder, so you can move it higher up in the tree without affecting the operation of this script.

About 'source': this is the old Silva Code Source location.  When Silva 0.9.3 (or perhaps 1.0?) was released, code sources no longer used this 'source' folder and were instead added directly in silva containers.

In this 'source' folder, add a Python Script.  Now edit your form's configuration (in the SMI).  To go the 'standard settings' screen.  The script should appear in the 'preload hook' field. note: place a graphic here?

Coding the Preload Hook

There are two parts to this script.  Getting the data, and placing it in the REQUEST.

Getting the data

The first part of the script needs to get the data you will be putting into the REQUEST.  This can be as simple as importing DateTime to get the current time (example 3), using REQUEST.AUTHENTICATED_USER.getId() to retrieve information about this user from the zope user folder, ldap or a database (example 1), or checking REQUEST for a set of parameters that control what data you're looking up (examle 2).

Let's see what a concrete example 2 would look like.  Given that on a separate page you link to this form with the following GET variable (?row_id=2), the first part of the script will look like:

#get row_id
row = context.REQUEST.get('row_id',None)
if row==None: #return message to user if no row_id
  context.REQUEST.set('form_message','invalid query')
  return
data = context.zsql_method(row_id=row).dictionaries()
if not data:  #no data for given row_id
   context.REQUEST.set('form_message','no data matching query')
   return
data = data[0]  #we only want one row.

Note that this script is only preloading data, so if there is no data, you can either give the user a message (see here for information about form_message) or do nothing at all.  This of course depends on how serious 'lack of data' is for this form.

Also note that you can use REQUEST.other or REQUEST.form.  The form fields pull from REQUEST (not REQUEST.form directly).

Placing data in REQUEST

Now that we have our preload data, we can place it in REQUEST.  This is really fairly simple.  You may want to write down the ids of the form fields you'll be preloading so you don't have to switch back to the SMI.

context.REQUEST.form['field1'] = data['field1_in_table']
context.REQUEST.form['field2'] = data['field2_in_table']
context.REQUEST.form['field3'] = data['field3_in_table']

If the script fails...

If the script fails, the error is caught and logged in the error_log.  The exception is NOT raised!  This script should not be making changes to anything besides REQUEST, so nothing should need to be rolled back.  Errors should only happen during form creation, anyways.  IF an error does occur, in the public view the form is rendered, but a msg is printed at the top (see here for info about this) stating there was an error in preload_hook, and what the error name was.