Posted Jan 12, 2009
Viewlets: barriers beyond borders
The Gloworm product makes it much easier for those new to Plone to identify and customize viewlets. But for Plone newbies, many barriers remain to understanding what viewlets are, why they are so useful, and how to manipulate them. Here are some of the pain points we've encountered.
Gloworm will get you on the road to understanding, but not all the way there...
Eric Steele pointed out in a recent post that the Gloworm product can help themers:
- identify what components of a rendered page reside in a particular viewlet
- customize any viewlet through-the-web (with some limitations: see below), and discard these customizations
- move a viewlet around within its viewlet manager, via a nicer user interface than the one which Plone offers (@@manage-viewlets)
Eric commented that Plone newbies can find it hard to understand viewlets, and that by putting a border around a viewlet (as Gloworm does, temporarily) a newbie can find it easier to see what's in what viewlet. Both these observations are undoubtedly true.
However, simply being able to identify which bits of a page sit in which viewlets is only a first step to understanding and manipulating viewlets. Plone newbies also need to understand several other things about viewlets before being able to really manipulate them. Some of these concepts are particularly tricky for newbies to grasp (and bear in mind that many people responsible for theming sites come from graphic design and other non-programming backgrounds).
I spend a lot of time helping people to learn Plone. Here's where I see much of the viewlet-related pain arising. It would be fantastic if future versions of Plone, and Plone documentation, could help alleviate these.
Viewlet code doesn't sit alongside other template code: either in the ZMI or on the filesystem
Page templates such as document_view.pt and folder_summary_view.pt live in portal_skins in the ZMI and in CMFPlone/skins/[someFolderOrOther] on the filesystem. If I want to find a page template via the ZMI, I simply use the "Find" tab to search for it by name or by the code I know it contains.
So viewlet templates ought to live in the same places, and be found in the same way, right?
Sadly, no. Major source of confusion for newbies, and for themers used to Plone 2.5.
In the ZMI, some of the viewlet code (the viewlet templates) can by accessed via "portal_view_customizations". However, this code cannot be found via the ZMI's "Find" tab. This inconsistency (some stuff findable via the "Find" tab, other stuff not) is perplexing to our newbies.
Furthermore, the stuff in portal_view_customizations is only part of the code relating to each viewlet: you can see the template-like code, but you can't see other important stuff via the ZMI: python classes, zcml and xml, all of which you may need to alter, depending on the type of customization you need to make (see below).
On the file system, viewlet code resides in packages called eggs. Our typical newbie has never heard of eggs, and may not even have come across similar concepts before. The fact that (depending on how Plone was installed) folders containing eggs may not be visible at all via tools like the Mac's Finder doesn't help.
"Why can't I just use X in my viewlet code, when it works in my page template?"
A themer new to Plone needs to understand the concept of a Zope page template (such as document_view.pt or folder_summary_view.pt). Essentially, a template looks at where it is being called, and then decides what to display (e.g., what XHTML elements to populate, and what their contents should be), and how to display it (what CSS classes and IDs to apply).
"OK, I get that. So viewlets are like mini templates, that each deal with a section of the page, right? Look: I can see this TAL stuff in this page template, and I can also see it in this viewlet template."
Er, kind of... but not exactly.
Viewlets need associated python classes... sometimes
Very simple viewlets do not need their own python classes. For example, if you want your viewlet to display the same block of text on every page in your site, you may not need a python class: all you need is a template that can render the relevant XHTML. Here is an example:
<p>Go to <a href="http://example.com">our main website</a></p>
However, if you want a viewlet to do something reasonably sophisticated -- such as not display certain contents to anonymous viewers, or show the current time and date, or only display when called by a particular content type -- it needs a python class to tell it what to display.
The fact that a viewlet often relies on an associated python class to provide data to be displayed is something that many newbies don't appreciate. Even when the python class requirement is pointed out, it often confuses Plone newbies, because "other page templates" (i.e., those in portal_skins) don't require one. For example, in author.pt or folder_summary_view.pt, I could simply use the following condition
<tal:onlyShowToLoggedInPeople tal:condition="not:isAnon">
Something we don't want anonymous users to see
</tal:onlyShowToLoggedInPeople>
to hide content from anonymous viewers, because "isAnon" is a variable available to all Zope page templates (it's defined in getMainGlobals.py). But if I want to use the same code in my viewlet, I have to define what "isAnon" is, using an associated python class (if I don't define "isAnon", I get an error message).
What's more, because it's my class, I don't need to use the specific term "isAnon" for the code to work. I could call my variable "anonymous" or "pancake" or "mountaineer", or anything else: I just have to make sure that the template calls "context/anonymous" or "context/pancake" or whatever. So different viewlet templates can contain different code that does the same thing, or the same code that does different things: very confusing to newbies.
You often need a filesystem theme product
Gloworm and portal_view_customizations are great... up to point. If you want to make certain minor changes to one of Plone's viewlets, you can indeed use these tools to effect the changes through-the-web, without touching the file system or python code.
But if you want to customize a Plone viewlet by getting it to display something that its default underlying python class doesn't compute for you, you need to write your own python class. Where do you put this class? Um, now you need to make something called a theme product.
Oh, and you want to make your own viewlet, to insert into the page among all the viewlets that come with Plone? Well you need a theme product for that too.
How do you make a theme product? Ah, well the best way to start is to use something like paster to make an egg for you. To get paster working on your machine you need something called ZopeSkel, which if you're on a Mac you can install with macports, but first you need to make sure you have Xcode... by which point, most newbies have developed a distinctly glazed look**.
** Many thanks to Joel Burton who has alleviated some of the "technology shock" pain for newbies, with his web-based version of paster. This can avoid many hours of frustration trying to install ZopeSkel and all its dependencies.
You mean I need to write Python code?!? Help!!!
Many Plone newbies are not just new to Plone, but new to Python and object-oriented programming... and even programming per se. Having to do apparently complicated stuff (python programming) to achieve apparently simple ends (changing some text on a page) can give some people the heebie jeebies.
What's "context"? I thought I knew, but now I'm not sure
Newbies learning to customize templates in portal_skins quickly learn that "context" means the place where the template is rendering. For example, if the document_view template is rendering a page called Financial Aid inside an Education section of our site, "context" means home/education/financial-aid. And if we want our template to display the title of the object we are on, we could write:
<h2 tal:content="context/Title">Page title here</h2>
Following this logic, it would be reasonable to assume that "context" is also the place where a viewlet renders. And, indeed, the above code does work in a viewlet template. However, when we try to call "context" inside the python class for our viewlet, we get an error to the effect that context is unknown... unless we know to call "self.context" instead of simply "context". To the python class, "self.context" is the viewlet in the context of the place it is called. Simple, yes, but not obvious to many newbies, and the cause of much gnashing of teeth.
Argh, ZCML: something else to learn (on top of TAL, METAL and Python)
Anyone putting a custom viewlet in their own theme product needs to register that viewlet using a configure.zcml file. Newbies have rarely encountered ZCML before. It's yet another thing to learn to deal with. It can take a while to appreciate that:
- the viewlet registration must either point directly to a template (if a python class is not required), or to a python class that itself points to a template... you shouldn't specify both a class and a template
- this is where you need to specify what viewlet manager should handle a custom viewlet
- the viewlet's manager must be specified by interface, not by name (and newbies often don't understand what interfaces are)
- A layer needs to be specified, so that the viewlet only appears when it should (again, newbies often don't understand layers, or how these relate to the "layers" of portal_skins)
In our experience, newbies typically regard ZCML as black magic.
Viewlets.xml and Generic Setup: yet more (gibber, drool)
If you want to do any of the following...
- Move one of Plone's default viewlets between viewlet managers
- Use a customized version of one of Plone's viewlets, and that customized version is sitting in a filesystem theme product
- Add your own viewlet in among Plone's viewlets
...you will need to specify these changes using a viewlets.xml file in your theme product's install profile (typically in profiles/default). In this file, you can:
- Hide one or more of Plone's default viewlets
- Specify where you want your custom viewlets to appear, in relation to the other viewlets in a particular viewlet manager
Oh, and by the way, if you have made certain changes and you want your theme product to uninstall cleanly, you will also need an uninstall profile containing another viewlets.xml.
Easy when you know it, but yet more complexity for our poor newbies.
In summary
New themers often want to make what they regard as minor customizations to an out-of-the box Plone 3 site. For example, they want to move the site actions to the footer, or make certain parts of the footer be invisible to anonymous viewers. So they can be flabbergasted to find that, in order to effect these "minor" changes, they need to make a filesystem theme product in which they need to change between two and five separate files (a template file, a python class, a zcml file and one or two viewlets.xml files), each of which requires a different "language" to modify (TAL, Python, ZCML and XML, respectively). They also need to understand how to select what they should do out of a range of possible things they could do (do I need a python class, a viewlets.xml, an uninstall profile?)
We often hear people say "theming used to be so much easier in Plone 2". Indeed, in Plone 2, the newbie just had to cope with page templates, TAL, and perhaps small amounts of in-template python. In Plone 3, there is so much more to understand before one can be productive.
Core Plone developers might be quite surprised at the things I have highlighted. Yes, it's all pretty obvious once you understand how it works. But it's complicated, and we should anything we can do to make it easier -- whether that be better documentation, or more tools to aid through-the-web customizations, or getting rid of ZCML and generic setup, or anything else. If we don't make it easier, we risk fewer people using Plone.

Not surprised
Thanks for writing this up! I'm not at all surprised by this pain, though :)
For Plone 4, we're considering some pretty radical changes to the way the page is composed and rendered, with much more power pushed into "simple" HTML or small templates that are easy to write. I hope that you won't need any XML or Python at all to do most simple operations, and only very simple Python for the ones that require a bit more power.
The fundamental problem at the moment is that we're not really using viewlets for the right things. Viewlets are great for creating pluggable UIs: I create this "space" here (a viewlet manager) where third party code can provide custom snippets to the user. We wanted to make Plone easy to extend, and so we moved lots of our UI into such pluggable spaces where they could be augmented or overridden. However, this was taking it all a step too far. Much of what's in viewlets (probably the stuff your themers want to move around) is really just part of a template, or part of a site layout.
In Plone 4, I think we'll see a model where we have a few viewlet managers for third party code to plug into, but the dynamic parts of the page are managed in a much more "flat" fashion. You'll probably get away with just dragging a few things in an HTML editor for most of your basic layout tasks. For more complete "branding" operations, we'll probably ship with Deliverance. See deliverances.openplans.org.
Martin
P.S.
Getting rid of GS would be wrong. However, you shouldn't need GS just to decide what boxes are shown on your site and which ones of the defaults to hide.