Tangled in the Threads
Jon Udell, August 20 1999Exploring Zope
The subject of Zope came up again this week, courtesy of Bjørn Borud:
Zope being Python (and Python making my aestheticle hurt) I haven't looked much at Zope. (It's funny how the unappealing look of the code has made me stay away from Python.) Could you sum up Zope in a few lines? Exactly what does it do?
In (msg) I laid out some of Zope's salient features.
- It's an industrial-strength version of my dhttp idea. Zope is a 100% scripted long-running HTTP daemon, which maps HTTP requests directly into scripted method calls.
- It's an ASP/JSP/ColdFusion-style template processor, where the template tag language is augmented by native method calls in the same script language (Python), and this is pretty quick because the engine itself is the aforementioned long-running Python daemon. The tag language also interpolates SQL calls and results very much as in ASP/JSP/ColdFusion.
- It's an object database whose structure maps to your site's structure, and which is also a persistent representation of a Python-ish class hierarchy. This makes it great for "factoring" the functionality of a site.
- It's a vehicle for the deployment of packaged "products" that plug into this architecture -- for example, there's a slashdot-alike called SquishDot which you install, very simply and cleanly, into Zope to add a slashdot-like component to a Zope site.
- It's a GUI admin interface on top of all this, so the site is fully Web-managed, and this includes advanced features like "sessions" in which you can explore alternate paths of development, which you can then commit or roll back.
- Since Zope is entirely Web-driven, it is automatically scriptable from the outside -- a huge point in its favor in my book.
There was a lot of discussion about Zope in the previous incarnation of the newsgroups. I'll summarize that here, and invite you to direct new Zope discussion to the programming newsgroup.
As I worked through my first Zope project, my first concern was a practical matter having to do with its object database. Does all content end up in there, I asked, or are there ways to reference file-system content that is transcluded into Zope and made available to Zope's DTML (document template markup language) and other mechanisms?
When you end up with lots of content chunks and templates, I'd rather have those things in a file system where I have 100 ways to get at them (including a text editor) than have them locked up in any kind of database (relation, object, or whatever).
This problem is as old as the hills, really. I remember when FoxPro was a hot thing, and its interface tried to convince you to stick snippets of code into all sorts of nooks and crannies that you could get at only through that interface. I always ended up putting references in those places to files that I could separately edit and manage.
Jeffrey Shell, whose Python insights have informed the newsgroups for years, and who works at Digital Creations, the maker of Zope, set me straight:
Everything, and we mean everything, lives in the object database.
Zope 2 supports FTP and WebDAV as alternate access mechanisms (through ZServer). There are a few folks here who prefer to edit in EMacs/XEmacs and use ange-ftp to work inside of a Zope site. We've used WebDAV as a way of putting huge amounts of HTML and Images (like HTML Generated from a UML Model) into Zope easily. Zope 2 also supports XML-RPC.
Zope 2 also uses ZODB3 which supports object storage in various mechanisms. I believe that there are new sample storages that show how to do an entirely-in-memory example (mainly to show how to implement a fully transactional/undoable storage mechanism) and a DBM one (which doesn't pick up the transactional/versioning mechanisms). It's conceivable that a purely file-based mechanism could be written. But you'd lose all of the advantages of ZODB (versioning, transactions, undo, security).
Fair enough. I've explored the idea of keeping node placeholders in Zope's object database, to enable its object magic, while sourcing content from the filesystem. This wouldn't be ideal, though, you'd lose a lot of the clean manageability of Zope. Ultimately to use it, I think you have to buy all the way in to the object database, and trust it, and see what happens.
HTML tabbed indexes in Zope
For my first mini-project I decided to reimplement the HTML tabbed-index feature that I often use to tie sets of pages together.
Typically I generate sets of pages containing this feature, using Perl to vary the treatment applied to active (clickable) tabs vs the current (not clickable) tab.
Here is the Zope solution I came up with. First, a pair of folder properties called tabnames and tabvals containing the names (HTML link labels) and values (filenames) of the pages controlled by this tabbed index. Then, an external method bound to the folder, which receives the name of the current document (doc_id) and constructs the right tabbed index for that page:
def TabbedIndex(self,doc_id): ret = "<center><font face=\"Arial, Helvetica\" color=\"#663333\">\n" for i in range(len(self.tabvals)): if ( doc_id == self.tabvals[i]): ret = ret + "<font size=\"+1\">" + self.tabnames[i] + "</font>" else: ret = ret + "<a href=\"" + self.tabvals[i] + "\">" + self.tabnames[i] + "</a>" if ( i < len(self.tabvals)-1 ): ret = ret + " " return ret + "\n</center>\n"Finally, a DTML construct that is standardly included in every page belonging to the index set:
<!--#var expr="TabbedIndex(document_id())"-->Robert Carey suggested some improvements to my (beginner) Python coding:
I have a tendency to write things the way you have here, probably because I have a Unix background. However, in Python you can use either single or double quotes interchangeably, and the one quotes the other. So it may be more readable to do:
ret = ret + '<font size="+1">' + self.tabnames[i] + '</font>'than to use backslashes to quote the individual quotes:
ret = ret + "<font size=\"+1\">" + self.tabnames[i] + "</font>"but obviously this is up to your personal taste.
Additionally, Python has a C-printf-like formatting operator. So you could say:
ret = ret + '<font size="+1"> %s </font>' % (self.tabnames[i])Lastly, and this I particularly like, Python has multiline strings. So you can say:
template = """<font size="+1"> %s </font>""" ret = ret + template % (self.tabnames[i])making the DTML block somewhat more readable.
Thanks Robert!
As an aside, note that in Perl you'd just say:
$ret = "<font size=\"+1\">$self->{tabnames}->[$i]</font>";The chief difference being that you can always interpolate a variable anywhere in a string. The nonreadability of \"+1\" is, however, an issue.
Zope's intoxicating technology
I have a feeling I'll be doing more with Zope. I'm particularly interested to hear from people who are using it for substantial projects. As Cameron Laird has said in an article on Zope, its technology is "intoxicating." Said Jeffrey Shell:
Zope, I believe, can really carry over something I believed was significant about Python: ease-of-graduating-into-bigger-better-things. When I first picked up Python, I was amazed at how easily I went from using the interpreter as a calculator to writing small scripts to writing bigger scripts with functions to writing classes.
DTML Scripting offers a fair amount of power while retaining the through-the-web security and flexibility of being able to update your site anywhere, anytime. External Methods bring full Python programmability into the mix in a still (relatively) easy manner.
Zope's packaged Products are really powerful, exploiting Python's strengths within a framework that takes care of persistence, security, and web management. These Products include, for example, an IMAP Adapter (written by our own Michel Pelletier) which connects to an IMAP Server and can make the folders/messages act like Zope objects. Another is the LDAP Connector that does a similar thing with LDAP Servers - turns them into a hierarchical tree navigable in the Zope management screens with the ability to update attributes, create new subobjects, all through Zope.
Last but not least is the fascinating story of how Zope came to be an Open Source project. As Jeffrey reported in our newsgroups last year, it was Digital Creations' venture capitalist who convinced the company this would be a smart move!
Toto, I don't think we're in Kansas anymore.
PS: If anyone's figured out how to attach IE5, WebDAV-style, to Zope 2, please let me know.
Jon Udell (http://udell.roninhouse.com/) was BYTE Magazine's executive editor for new media, the architect of the original www.byte.com, and author of BYTE's Web Project column. He's now an independent Web/Internet consultant, and is the author of Practical Internet Groupware, forthcoming from O'Reilly and Associates.