Could it be possible to make viewlets simple again?

Viewlets were introduced in Plone 2.5 and they are extensively utilized in Plone 3.0. Viewlets are controlling the snippets of web pages and you must understand them if you wish to add new Plone UI elements or create new Plone themes. This new technology promises to separate Python based logic from page templates, thus making HTML authoring a cleaner process. On the other hand, it introduces new elements to Plone technology soup, further bumping already steep Plone learning curve. Could we avoid this learning bump and keeping simple changes simple.

I present not-so-rare scenario where a newbie wants to add a new piece of HTML code to every Plone page. I use a custom language bar as an example: instead of using the normal language selector, provided by Plone or LinguaPlone extension, our newbie developr wants to style a language bar suitable to his/her site theme and have it in non-standard location on the page.

1. Old way

In Plone 2.5, much of the Plone HTML output were controlled by two things

  • TAL templates
  • Python scripts, standalone or inlined into templates

To add a new item to the portal header section, let’s call it a custom language bar, you had to do the following.

  • Open a sample Plone page in the browser
  • Use Firebug to identify related CSS ids in the page you are viewing
  • Search through Plone page templates for these ids
  • Identify the template which produces the piece you are going to modify. You might had to follow metal:define-macro and metal:define-slot chains a bit, but generally this all could be achieved with simple source tree searches. In our case, this template was global_languageselector.pt.
  • Make a copy of this template.
  • Insert your own template code to produce the customized language bar.
  • Modify main_template.pt or similar file to add metal:use-macro entry which will place the new template no the page
  • If there are any problems with the page template files, they are detected on-the-fly and you can fix errors by just reloading the page

Voila! 7 steps. One had to understand HTML, CSS, Firebug, TAL and little bit Python now and then. This is nothing too difficult for an average Joe.

2. Plone 3.0 way

Plone 3.0 has a system with containers and viewlets. All viewlets are bind to a certain container, in which they can shuffled and hide (even through-the-web!) .

Pros:

  • New products can register their own viewlets without messing up other site layout customizations: no conflicting main_template.pt overrides.

Cons:

  • Through-the-web layout editing is really limited. You cannot move item away from one container area to another. You still need to do CSS and page template editing to make more advanced customization i.e. anything more complex than moving the logo to the right side of the page.
  • There is an additional technology layer in the HTML output system, making mastering this system difficult
  • This viewlet stuff is generally quite developer oriented. It feels like top developers have been writing things for other top developers. Average Joe has been forgotten in the some point of evolution.

Below are steps what we need to create the imaginary custom language bar in Plone 3.0. This is not the exact recipe, but I guess you all get the point along the lines…

  • Use @@manage-viewlets to see what containers exist in the page area you want to add your custom HTML piece
  • Search through ZCML files to see how these containers are defined
  • Create a new Python file: interfaces.py
  • Create a new Python file: viewlets.py
  • Create a new profile (GenericProfile) file: viewlets.xml
  • Create a new container which will be placed between somewhere between the existing container
    • Define the interface for your new container
    • Register new interface in configure.zcml
    • Position your container in viewlets.xml
  • Create a new language bar
    • Locate the Python class which the old language bar viewlet implementation uses. Copy-paste its code to your new MyLanguageBar viewlet class or try extend the base class and hope you don’t need to copy-paste that much of code.
    • Create a new template my_languagebar.pt, copy-paste the content from global_languagebar.pt
    • Place your viewlet in the new container in viewlets.xml
    • Register your viewlet in configure.zcml
  • Restart Zope.
  • Fix ZCML typos.
  • Restart Zope.
  • Reinstall your product.
  • Fix Python syntax errors.
  • Restart Zope.
  • Reinstall your product.
  • Fix page template errors.
  • … and so on

Phew. In this point we have at least 2 python modules, 1 page template file, 2 different XML dialects, 150 lines of Python code. You need to master following technologies: HTML, CSS, TAL, @@manage-viewlets, object-oriented Python, Zope Component Architecture, ZCML and GenericProfile XML. The five latter ones don’t actually have anything to do with the job, changing a bit of HTML code. Basically this means that anyone who wants to pimp his/her Plone must have PhD in software architectures.

Why would you need to be Enterprise Software Architecture to make a simple HTML change? I am afraid that the new Plone way of HTML authoring will drive people futher away from Plone, because they just can’t do it(tm) anymore. Plone is already enjoying bad ass learning curve. Making it even steeper and forcing people to learn things which are not really related to their jobs won’t make Plone more attractive. I am afraid that soon there might be only three people left in this world how actually have the skillset to create new Plone skins (Alexander Limi, David Convent and Denis Mishunov).

3. Could it be easier?

The bitter comments in viewlets tutorial indicate that not everyone loves the new way. Though we need a system like this to make Plone flexible, somewhere along the way architecture just got little too complex. Maybe we should be a bit more Grok‘ish and try to hide all this complexity from novices. These two principles help in designing a system:

  • KISS (Keep It Simple Stupid): The infamous learning curve. Is it really necessary to create a new Python class and play around with ZCML to spit out value True instead of False in some point of rendering chain?
  • DRY (Don’t repeat yourself): Don’t force the developer type anything twice. Why you need to have IMyLanguageBar, MyLangugeBar, mylanguagebar.py, <browser:viewlet name=”myLanguageBar”, my_language_bar.pt, tal:define-macro=”my_language_bar”, #my-language-bar and so on… when this all could be generated by the system with some intelligence in it? Too many files, the same stuff in different wrapping.

My dream is that to accomplish something you need as few lines and few files as possible. Preferably one file for one thing. No changes in other files needed.

It could be something like this (indent problems below!):

myproduct/browser/viewlets/my_languagebar.pt

<html xmlns="http://www.w3.org/1999/xhtml">
<plone:viewlet="my_languagebar"  to-slot="portal-top"

default-visibility="true"
  default-order="after:logo"

bind-data="showCurrentLanguage python:True">

<ul>

<li>Choose Finnish</li>

<li>Choose English</li> </ul> </plone:viewlet>

</html> Explanation: Let’s add viewlet my_languagebar to portal_top container and by default it should be placed after logo viewlet. The HTML code is all there. We override context variable showCurrentLanguage with inline Python script.

  • Only one file needed! Forget interfaces.py, viewlets.py, configure.zcml, Python classes and other extra XML sit-ups.
  • You are doing the definition in good old TAL using custom Plone tags. Forget learning of ZCML or GenericProfile XML.
  • This file is picked up automatically, you don’t need to mess with configuration files. When you are doing changes you need to do them in one place only. People love this kind of magic if the alternative is XML sit-ups.
  • All viewlet context specific variables are clearly visible in TAL and you can override them without creating a new Python class, using TALES definitions or Python scripts. You don’t need to go for long subclassing path just to tweak one context variable or HTML template name.
  • Ordering clearly states that it’s default ordering and the site administrator can resolve conflicts using @@manage-viewlets. We don’t need separate <order> and <hidden> sections as in viewlets.xml.
  • Less typing, less technologies, less mess = more productivity = more fun = more fans = Plone prevails

Now, let’s unleash the debate dogs and let them bite this blog 🙂

Technorati tags:

12 thoughts on “Could it be possible to make viewlets simple again?

  1. You’re leaving one fundamental detail of information out. You can still just do the old style way of customizing the main template (or just the templates of the viewlets you care about).

    If you *want* the flexibility of using the viewlets to make changes (which are far more upgrade proof than customizing plone templates) then you can do the viewlet dance you describe above. Although I do agree that making new viewlets and setting them up, etc, could be made much easier.

  2. Pingback: Could it be possible to make viewlets simple again? | yourmuses

  3. Rocky, you are right. You can tweak main_template.pt with no problems. The problems appear when you need to change something inside viewlet containers: between viewlets or add new containers (basically all portal_header stuff). Since order and content in the containers are defined (programmatically) in ZCML, GenericProfiles & co. you must go this route to change them. You can tune individual viewlet template with macro hacking, but that’s quite limited.

  4. You can just register a template in your zcml, no need for python files. Then you only need the viewlets.xml GS profile part to place it, because that just doesn’t belong in the template. The template has nothing to do with where something is placed, just how it looks.
    I also don’t understand what this means “Create a new container which will be placed between somewhere between the existing container”. If you want to change an existing viewlet, just use your own skin, add a zope 3 skin layer to it (all done automatically by DIY Plone Style) and register your viewlet under the original name, just with the new layer.
    And subclassing is way better than the old way where you had to copy the whole python script and template and customize them. It’s also easier for upgrades, because you don’t have to track as many changes.

  5. Hi Florian,

    Your answer reflect much of a developer attidude and I think you miss the point of the blog: I don’t want technical answers, I want to point out that viewlet system is too complex for non-pro developers and how it could be improved. You understand ZCML and such stuff when you typed your answer out of your head – normal people don’t know these things. And why should they?

    – The template has nothing to do with where something is placed

    Only in the engineer world which is full of rectangles and 90 degree corners. Look at this layout: http://www.amnesty.ch/en See word Contact. It has a special border. Thus, the template rendering the word has a lot of do where it is placed.

    – You can just register a template in your zcml, no need for python files.

    Why do I have to do this? Why my templates aren’t picked automatically like in plone_skins?

    – The template has nothing to do with where something is placed, just how it looks.

    Only in the ideal world. Templates need data. Data comes from viewlet classes. Often you need to transform this data suitable for templates. To change the data, even a tiny bit, you need to subclass/recreate the viewlet class. This is cumbersome.

    – Register your viewlet under the original name, just with the new layer.

    New layer = WTF says Average Joe.

    Register viewlet = WTF says Average Joe.

    – And subclassing is way better than the old way where you had to copy the whole python script and template and customize them.

    This is true, as I told the post. It makes possible to extend Plone cleanly. But it’s also a cumbersome way to make small changes. Skin/template developers must be aware of a lot of things which they shouldn’t (ZCML, Python, ZCA and so on).

  6. Thanks for this nice article, Mikko. I was missing the points that you make here in the recent discussion about TTW or not.

    The templating system needs to be easy to understand for front-end developers. It’s NOT (only) about whether everything can be customized through the web or not.

    Now if all these steps give me a headache already, how am I supposed to explain this to my fellow HTML/designer person, who really wants to use a version control system?

    I think that the vague benefit of “can track changes easier” (anyone heard of diff?) is in no relation to the downsides.

    I’m seeing UI people that are confused today with how Plone 2.5 is put together, and we’re just adding to the complexity…

  7. Hey Mikko. I don’t know anything about Plone viewlets, and little as yet about viewlets. To those defending the current state of viewlets in Plone: I realize that all this complexity you describe has value (Five is one of underlying enablers of both the features and complexity now, so I indirectly had a little to do with this).

    I also like the constructive and well-researched criticism and your goal to simplify. So forgive me the recruitement attempt: please join the grok-dev mailing list if you haven’t already and make sure that when we get to viewlets, we do it right?

    What does it mean to do it right? The Grok approach is this: we keep the essential flexibility but don’t let it get in your way, by providing sensible defaults and minimizing repetition.

    There is a tension there with explicit configuration and the complexity that results in, but there’s also a lot of synergy. In fact I think Grok is a much better framework thanks to it being based on Zope 3, a framework with a strong attitude towards explicit configuration. When we developed Grok we didn’t need to rebuild Zope 3, we just needed to add automation on top of it. Zope 3’s explicitness pointed out what we could automate and how. Similarly I hope the complexity of configuration of viewlets today can be a great help in identifying what Grok should be doing by default and what flexibility points it should be providing.

  8. You can do many of these customizations using the portal_view_customizations tool – erm, except for the languageselector template, that template isn’t editable because of a simple bug. It’s just that few know about the existence of this tool yet (despite the fact that the source package has an awesome name – plone.app.customerize).

    What would be helpful is if @@manage-viewlets had an [edit] button for each viewlet that took you to a TTP (through-the-plone) page that let you edit a given template instead of needing to hunt around the scary ol’ ZMI for ‘portal_view_customizations’. This would probably be quite easy to do as well. It would also rock if you could move viewlets from one container to another in @@manage-viewlets, although that would be a harder UI to support – although perhaps with some of that fancy new KSS it wouldn’t be too hard to implement.

    This only addresses “template-only” customizations though. If you want to create a viewlet backed by a custom Python class you are going to hit that much larger learning curve.

  9. Pingback: Confluence: Pakki 2

  10. Not to sound elitist or anything, but Average Joes who were convinced to use Plone for anything more than CMS (“you can customize it yourself!”, etc) got conned. Plone development is not for the faint of heart or weak of stomach. Some of it is due to the use of advanced (or just many) concepts, but a lot of it is just the pure insanity of the volatile domain space and the pulled-in-all-directions development model.

    A lot of the problems in Zope2 and Plone are, IMHO, due to an overconsideration of Average Joes, who at one time were going to build their own applications with ZClasses (since what Average Joe fears above all else are text editors — textareas are A-OK!). It has added many layers of useless complexity. I’m all for enabling Average Joes, but I think that is better accomplished through quality documentation than code contortions that attempt to hide rather than reduce complexity.

    That said, what I’ve seen of Grok rocks!

Leave a Reply

Your email address will not be published. Required fields are marked *