Web Services Wiki
Welcome Guest: Login
Under some circumstances you want to preload form fields with data. Some example uses of this would be to:
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.
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" |
|
|
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).
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?
There are two parts to this script. Getting the data, and placing it in the REQUEST.
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).
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, 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.