ZClass Properties
Created by .
Last modified on 2003/08/05.
I'm no expert on ZClasses, but,
while implementing my first ZClasses,
I learned some things that I could not find in the "Zope Developer's Guide".
Most of the following information was published on the [email protected] mailing list by
Michel Pelletier, Kevin Dangoor, and Toby Dickenson,
but any inaccuracies that you may find were probably introduced by me.
ZClasses are Zope's way of providing extensible, sharable, persistent objects.
If you are new to object-oriented programming, I'd recommend that you start your education not with Z Classes (which are complicated by the interactive environment they are designed to serve), but rather with a more self-contained object implementation (such as Python itself).
In the field of object-orientented programming, the terms "class variables" and "instance variables" are often used for the data structures that are common to all methods of a class or of an object that is an instance of that class. There are many variations on how these variables can be used, with a corresponding number terms to describe the various uses. For example, you may want a given data item to be a constant that is shared by all instances; the constant can be changed only by changing the class definition. Or, you may want a given data item to have a different value in each instance, but be constant within that instance; i.e. not changed by any method. Or, you may want a data item to serve a common function in each instance, but contain values that are determined by the methods of that instance.
In Zope, "property sheets" are used to implement all varieties of class and instance variables.
A class can have multiple property sheets
(though many classes will have only one).
Each property sheet can define one or more variables,
which are called "properties".
Among the many steps you take to create a Z-Class,
you have four opportunities
to determine the way a property can be used:
- In defining the property sheets.
The permissions assigned to a property sheet determine who can modify the properties it contains. And even when permission might be the same for different property sheets, the names of the property sheets can serve as brief documentation of the intended uses of the properties they contain. For example, 'SharedConstants', 'InstanceConstants', 'InstanceVariables'.
- In defining the property.
A default value can be supplied. If there exists no other means to change property values, the default value will be a constant shared among all instances.
- By calling manage_editProperties in the object constructor method.
You can set different property values for each instance, or the same default value for all instances. If you add fields for properties to the HTML form on the management screen.
- By calling manage_editProperties from the class methods.
Instances will be able to independently change their properties if they are given property editing methods.
The "Zope Developer's Guide" takes you thru the basic steps to create a very simple Z Class. However, because its example is so simple, that tutorial leaves out some important details related to property sheets. Let's take a slightly more meaty example and fill in some of those details. Suppose we want to create a "PDF Class" -- a class for uploading and storing files in Adobe Acrobat's PDF format. Now don't get excited -- this is not the "PDF Class" of your dreams. Not yet, anyway. This class will be similar to the File class, but will create a new meta-type, so we can easily identify PDF objects, and will ensure that every PDF file has certain data items (properties) that tell us what we need to know about the contents of the file. Follow the "Z Classes" chapter of the "Zope Developer's Guide", if you wish, as we create a PDF Class.
- Start at the Control_Panel, select Product Management, and add a new product with the ID "PDFProduct".
- Enter the "PDFProduct" folder, and create a Z Class by selecting "Z Class" from the product add list. Give it the ID "PDFClass", and for the "Meta type" specify "PDF File". From the "Base classes" select first "CatalogAware" (if you want catalog aware objects), then select "File". Click "Add" to create the new class.
Zope creates five objects for you: a Z Class called "PDFClass", two DTML methods "PDFClass_add" and "PDFClass_addForm", one "Zope Permission" called "PDFClass_add_permission", and a Factory called "PDFClass_factory".
NOTE: The two DTML methods "PDFClass_add" and "PDFClass_addForm" are just stubs that you will probably have to modify later, after you define the properties of this class and decide how you want the properties to be handled as an instance is created.
- At /Control_Panel / Products / PDFProduct / PDFClass, start creating a property sheet by selecting the "Property Sheets" tab, then clicking the "Add" button. Enter the ID "InstanceConstants", and click the "Add" button. Now you should see the "InstanceConstants" property sheet listed, with no properties defined.
- Create a property with ID "title", type "string", and empty value. Click "Add". You should now see "title" listed as a property.
- Create aonther property, this one with ID "pub_date", type "date", and empty value. Click "Add". As of this writing (October 12, 1999), this will cause an error "Invalid Date-Time String" because an empty value is not a valid date. There are some other data types for which the empty value is not valid; for example, "int" and "float". This problem may be fixed by the time you read this document.
- So, return and try again, this time with ID "pub_date", type "date", and value "January 1, 1970". This should work.
- Go back to the "Property Sheets" tab at /Control_Panel / Products / PDFProduct / PDFClass. You see only the "InstanceConstants" property sheet listed. We called it "InstanceConstants" because the data items we put there ("title" and "pub_date") are constant for each PDF file instance; they probably will not change for the lifetime of the PDF file. If we click the "Add" button again, we could create more property sheets. We might, for example, create a "InstanceVariables" property sheet that holds an "access_count" property that gets incremented each time the PDF File object is accessed. But, for the sake of brevity, we won't do that now. (That could be the subject for another "How-To".)
-
Now, go all the way back to the class folder, /Control_Panel / Products / PDFProduct / PDFClass, and select the "Views" tab.
A View is a management screen which is available via a management tab.
You will see that several Views have already been created for us. These were inherited from the "File" class.
However, because we have properties that are different from those of the "File" class, we want to override the "Properties" view.
Check the "Properties" entry, then use its drop-down list to select "propertysheets/InstanceConstants/manage", then click the "Change" button.
The "Z Classes" chapter of the "Zope Developer's Guide" says you are finished building the class at this point, and can proceed to create an instance. However, if you do that for this class, you will not get what you want. When we create an instance of "PDFClass", we want to upload the PDF file and attach its title and publication date. To do that, we have to complete a few more steps:
- Return to the Contents tab at /Control_Panel / Products / PDFProduct, and look at "PDFClass_addForm". It probably contains a form that looks like this:
<form action="PDFClass_add"><table>
<tr><th>Id</th>
<td><input type=text name=id></td>
</tr>
<tr><td></td><td><input type=submit value=" Add "></td></tr>
</table></form>
This form only asks for the ID of the PDF file object. We need to add code to make it look like this:
<form action="PDFClass_add" enctype="multipart/form-data" method=post><table>
<tr><th>Id:</th>
<td><input type=text name="id"></td>
</tr>
<tr><th>Title:</th>
<td><input type=text name="title" size=50></td>
</tr>
<tr><th>Pub Date:</th>
<td><input type=text name="pub_date"></td>
</tr>
<tr><th>File:</th>
<td><input type=file name="file"></td>
</tr>
<tr><td></td><td><input type=submit value=" Add "></td></tr>
</table></form>
Then click the "Change" button. Here we've added form fields for the other properties and for the file we are going to upload. Also, we added "enctype" and "method" to the form definition to handle the file upload.
- Return to the Contents tab at /Control_Panel / Products / PDFProduct, and look at "PDFClass_add".
There you will see the following line in comments:
<!--#call "propertysheets.Basic.manage_editProperties(REQUEST)"-->
.
We need to uncomment this line and replace "Basic" with "InstanceConstants" (the name of our property sheet), giving: <!--#call "propertysheets.InstanceConstants.manage_editProperties(REQUEST)"-->
. Then click the "Change" button.
This puts the fields from the add form (which are temporarily held in the REQUEST structure) into the property sheet in Zope's database.
Now, we're ready to create an instance.
Let's go back to Zope's root level (or any other folder that's convenient for you)
and create a folder called (just for example) "PDFClassTest".
Make the index_html method of "PDFClassTest" look like this:
<!--#var standard_html_header-->
<h2><!--#var title_or_id--></h2>
<p><!--#var doc_list-->
<!--#var standard_html_footer-->
Now create the DTML method "doc_list" like this:
<!-- Start Document List -->
<table border=0 cellspacing=4 cellpadding=2 width="100%">
<tr bgcolor="#DDEECC">
<td><b>Title</b></td><td align="center">Pub Date</td>
</tr>
<!--#in "PARENTS[0].objectValues(['PDF File'])" sort=id-->
<tr bgcolor="#DDEECC">
<td>
<a href="<!--#var id url_quote-->"><!--#var title--></a>
</td><td align="center">
<dtml-var pub_date>
</td>
</tr>
<!--#/in-->
</table>
<!-- End Document List -->
This method simply creates a table that lists the properties of each "PDF File" in the folder.
Now, in folder "PDFClassTest" use the "Available Objects" drop-down list and select the "PDF File" type.
You will see the form that we and Zope created earlier.
Fill in the fields, select the file you want to upload,
and click the "Add" button. You will now see your newly uploaded file listed on the management menu.
Click on the "View" tab and you will see an index that includes your new file and shows its properties.
Now wasn't that easy?
Note that property sheets are themselves Python objects.
You can read more about them in the Zope source files
../lib/python/ZClasses/Property.py and ../lib/python/OFS/PropertySheets.py.
Note that the ZClass implementation is somewhat different
than the OFS implementation.
Property sheet objects have several methods
available for us to use to operate on property sheets.
Because we have given our property sheet
a non-standard name,
we now have to qualify calls to those methods.
For example:
<dtml-if "propertysheets.InstanceConstants.hasProperty('pub_date')">
See also: