[Grok-dev] Re: Portlets (and maybe other skinning).

Martin Aspeli optilude at gmx.net
Tue Mar 20 03:54:13 EDT 2007

Lennart Regebro wrote:
> On 2/4/07, Lennart Regebro <regebro at gmail.com> wrote:
>> Also, some sort of portlets system would be needed. Does anything
>> (except the overworked and presumably now dead cpsskins for zope3)
>> exist?

Jumping in here, slightly ignorant of the discussion, but Philipp helped 
me a lot when I made plone.portlets, and it should be general enough to 
work in a pure-zope3 environment.

There is also plone.app.portlets which provides a Plone UI + Plone's 
default set of portlets. You'd need something similar (megrok.portlets).

I would be very happy to help anyone working on this.

In brief, plone.portlets[1] uses a design that's similiar to viewlets, 
and relies on zope.contentprovider. Unlike viewlets, however, the 
assumption is that you want to move portlets around a runtime and save 
the assignment of portlets at runtime. Portlets in plone.app.portlets 
can be assigned to locations (and may be inherited from parent 
locations), users, groups or content types, though at the plone.portlets 
level this is abstracted into "categories" (though there is some special 
handling of the location-based/parent-inheriting/parent-blocking 

There are a few components:

  - A "portlet manager" is a bit like a viewlet manager. You can think 
of it as a column.

  - A "portlet assignment" is a persistent object which keeps track of 
an assignment of a portlet to a particular portlet manager, in a 
particular category or context ("a login portlet shown if the user is 
optilude", "a recent changes portlet shown in location /foo and its 
children unless blocked").

  - A "portlet data provider" provides information about what is being 
rendered. Often, this is the same object as the assignment (the 
assignment has a method "data" which returns the data provider). The 
separation exists so that you can have a generic assignment type that 
points to e.g. content objects, which are then rendered by ...

  - A "portlet renderer", basically a view on a portlet (multi-adapts 
context, request, view, portlet manager, portlet data provider).

  - A "portlet manager renderer" is similarly a view onto a portlet 
manager, with responsibility for rendering the portlet manger/column.

  - A "portlet type" is a utility that informs the portlet management UI 
of which types of portlets are addable. It gives a name, a description, 
and an addview that can be used to configure and instantiate the portlet.

In plone.app.portlets, we also have some GenericSetup syntax for setting 
adding new portlet types locally, and adding new portlet 
managers/columns (these are registered as local utilities so that they 
are easy to find again, and we also register a local adapter factory 
that can instantiate the portlet manager *renderer* in response to a 
provider: expression).

All this means that in Plone's main_template (or a custom skin) you can 
do this:

<div tal:replace="structure provider:plone.leftcolumn" /> and you get 
the plone.leftcolumn portlet manager. Some clever view registrations 
also means that you get a generic portlet management UI for this column 
"for free". A custom skin could add a new column that is not in stock 
Plone and, when a use goes to the @@manage-portlets view, they'd get a 
portlet management screen for that column as well as Plone's standard 
columns. This UI is in plone.app.portlets[2], of course, so it wouldn't 
apply to Grok, but it may be useful as an example.

There is a doctest that walks through all these concepts: 

I must admit I haven't tested it in Zope 3, but it runs fine on Zope 
2.10 and I don't think there are any funny dependencies there.

You may need plone.memoize[3] I can't quite remember. This should also 
work without Zope 2 though.


[1] http://cheeseshop.python.org/pypi/plone.portlets ; 

[2] http://svn.plone.org/svn/plone/plone.app.portlets

[3] http://cheeseshop.python.org/pypi/plone.memoize ; 

More information about the Grok-dev mailing list