Portlets in Plone 3 are not too dissimilar to viewlets, but they consist of a persistent component, the portlet assignment, containing the configuration of the portlet, which is rendered using a portlet renderer. For visual customisations, you want to get at the portlet renderer.
Since portlet renderers can incorporate complex logic and relies on some specific registration techniques, Plone comes with a new ZCML directive - <plone:portletRenderer /> - which makes customising portlet renderers a little easier. Unlike the customisation we have seen for standard browser resources, a template-only custom portlet renderer will actually use the renderer view class (as its view variable) that was used to register the original portlet renderer.
In plone.app.portlets, under portlets/configure.zcml, you will find this definition for the Recent portlet:
<plone:portlet name="portlets.Recent" interface=".recent.IRecentPortlet" assignment=".recent.Assignment" renderer=".recent.Renderer" addview=".recent.AddForm" editview=".recent.EditForm" />
Let's say we wanted to customise this with a new template. The default template (as referenced by the Renderer class in recent.py) is recent.pt in the same directory. Copying that to our own package, we can do the following:
<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" xmlns:plone="http://namespaces.plone.org/plone" i18n_domain="example.customization"> <!-- We need to include the package of the portlets we are customising --> <include package="plone.app.portlets" /> ... <plone:portletRenderer portlet="plone.app.portlets.portlets.recent.IRecentPortlet" layer=".interfaces.IExampleCustomization" template="mostly_recent.pt" /> </configure>
Note that we are explicitly including the plone.app.portlets package in ZCML processing, since we are now using its portlet Renderer class implicitly. We then define a new portlet renderer with a custom template, for our new layer. It is also possible to use the for attribute to customise for a particular type of context, or the view attribute to customise for a particular view, as with viewlets.
Instead of using a custom template, we could use a whole new renderer class. See the implementations in plone.app.portlets to understand how this would work. Note that unlike views and viewlets, portlet renderers support either template or class, but not both.