Writing Zope Products
helloworld.py is a perfectly legal Zope product; we can install it in lib/python/Products, and Zope will not mind. Unfortunately, Zope also will fail to notice that helloworld.py is there at all, will not add it to the Add selection list and generally will ignore the work we did in writing our product. It's clear that we will need to beef up our skeletal product if we want it to interact with Zope. We will call this enhanced version the “smallhello” product.
For starters, we must change the structure of our product from a single standalone module file (helloworld.py) into a full-fledged Python package. A package is a directory (smallhello) within the Python search path (defined by the variable sys.path) containing one or more Python source files. In our case, the smallhello directory will contain two files: a smallhello.py file that is quite similar to helloworld.py (see Listing 2) and __init__.py (see Listing 3), which initializes and helps to register our object.
The __init__.py file first imports smallhello.smallhello, defining the module's methods and attributes. But the crucial part of __init__.py, at least as far as Zope is concerned, is the initialize method. After Zope discovers and imports smallhello, it invokes smallhello.initialize, passing it a ProductContext object (called “context”). In other words, initializing an object results in that object registering itself with the server.
The initialize routine itself is pretty straightforward, although our version does some rudimentary error trapping (using try/except) to ensure that things work correctly. Our smallhello product only passes two arguments to context.registerClass: the finalhello.finalhello object that we want to add and then a tuple of constructors that should be invoked when we want to create a new instance of our product. Remember to include a trailing comma if you pass a single item to constructors; otherwise, Zope will fail to load the product.
The constructors parameter is just one of a number of named parameters that we can pass to context.registerClass to customize the way in which our object is registered with Zope. For example, we also can pass an icon parameter that tells Zope which graphic (a filename inside of our package directory) should be placed next to instances of our package within Zope.
Turning helloworld.py into smallhello.py (see Listing 2) requires some small changes. We start by adding a method that allows Zope to create new instances of our product. By convention, such management-related methods begin with manage_, so our method is called manage_smallhello. This is the same method that was named in the constructors tuple passed to context.registerClass.
The most significant change to our smallhello class is also one of the least obvious: we have made it a subclass of OFS.SimpleItem.SimpleItem, one of the Zope product base classes provided as part of the Zope package (in the OFS.SimpleItem package). Without inheriting from SimpleItem, many things—from cutting and pasting of objects to acquisition—would fail to work as we expect, if at all. There are several possible base classes from which your products can inherit; SimpleItem, as its name implies, is designed to be the simplest and most straightforward of the bunch.
While modifying smallhello.py, I decided to add two other methods that produce content. One of them, other_html, produces output that is similar to index_html—except, of course, index_html is displayed by default when no other method is specified, while other_html only is called when explicitly named in the URL.
I also added a foo_file method that demonstrates how to return the contents of an HTML (or DTML) file from disk. It can be annoying and frustrating to put all of your HTML inside a Python module file; this way, you can keep the DTML files inside of the package directory but modify them independently of the program itself. Note that we had to import the HTMLFile method from the Globals package in order for this to work.
I modified the __init__ function in smallhello.py to take three arguments: self, id and title. (Previously, it only accepted self and id.) The __init__ function is invoked each time a new instance of smallhello.py is created, which is done through a call to manage_smallhello. Inside of manage_smallhello, our call to self._setObject sets the object ID to a generic smallhello_id, with a title of smallhello_title. Because we hard code the ID in our example, and because IDs must be unique within a folder, this means that we only can have one instance of our smallhello product in a given folder. There isn't enough space here to describe how to read and write parameters, but a quick look at the examples mentioned in the Resources section should make it obvious how to do this.
After the call to self._setObject, manage_smallhello then redirects the user's browser to the main (index_html) method. We could display some output instead, redirecting the user's browser to another method in our object, but I took the easy way out and decided to send users to /index.html on our site.
After you have installed the smallhello product, you can stop Zope and restart it again. You should see “smallhello” near the bottom of the Add menu; selecting it will send you to the index.html page on your Zope site. Because we haven't made our product as user-friendly as it could be, you will have to enter the URL manually (index_html, other_html or foo_file) in your browser. But there isn't any reason why these pages cannot contain links to each other or why other pages on the site cannot link to them.
What do you know? We've created a Zope product!
|Designing Electronics with Linux||May 22, 2013|
|Dynamic DNS—an Object Lesson in Problem Solving||May 21, 2013|
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
- Nice article, thanks for the
1 hour 5 min ago
- I once had a better way I
6 hours 51 min ago
- Not only you I too assumed
7 hours 8 min ago
- another very interesting
9 hours 1 min ago
- Reply to comment | Linux Journal
10 hours 55 min ago
- Reply to comment | Linux Journal
17 hours 49 min ago
- Reply to comment | Linux Journal
18 hours 5 min ago
- Favorite (and easily brute-forced) pw's
19 hours 56 min ago
- Have you tried Boxen? It's a
1 day 1 hour ago
- seo services in india
1 day 6 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi
It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?