[Grok-dev] Re: Giving viewlets "the grok treatment"?
optilude at gmx.net
Sun May 11 07:25:22 EDT 2008
> Well, I am actually building a somewhat pluggable UI, but with a
> fairly rigid and narrow set of "entry points" like "project creation
> options", "project info options", "user account options", etc. So I
> don't need a whole lot of rich options about how things plug into
> those particular places, but I do need a way to aggregate and display
> an arbitrary number of UI plugins without knowing what they'll be. I
> don't have very much experience with "vanilla" content providers; can
> they provide that aggregation for me by default? (That is, without my
> writing extra code in the content provider which aggregates broadcast
> plugins before returning them to the template.)
> I may be wrong, but my rough abstract understanding of viewlets and
> content providers is:
> * Content providers let you plug any, but not all, of (X, Y, Z, ...)
> into A, by allowing a single lookup on (context, request, view).
> * Viewlets with viewlet managers let you plug any or all of (X, Y, Z,
> ...) into any or all of (A, B, C, ...), by allowing a single lookup on
> (context, request, view) for the viewlet manager which then does a
> multi-lookup on (context, request, view, manager).
Kind of, but I think there's an easier way to look at this.
- zope.contentprovider is a low-level package. It defines an interface
IContentProvider, which is a bit like an IBrowserView. It also defines a
TAL expression type, "provider:", that lets you pull an IContentProvider
into a template. It does so by looking up a named adapter on (context,
request, view,) providing IContentProvider.
You can think of a "content provider" almost as a ZPT macro that's
looked up (and thus can be overridden) via the adapter registry, and
which has two-phase rendering (update, then render).
- zope.viewlet uses zope.contentprovider to implement pluggable UIs.
It defines an IViewletManager that is a special kind of
IContentProvider. When using viewlets, you use e.g.
tal:replace="structure provider:my.viewletmanger" in a template. That
renders the viewlet manager with name "my.viewletmanger" that's
appropriate for the current (context, request, view,).
- This in turn will look up all viewlets that are registered for this
viewlet manager and render them in order. The default implementation
uses the adapter registry to look up IViewlet adapters registered for
(context, request, view, viewlet_manager,), although other
implementations are possible.
Thus, the viewlet manager/viewlet framework is a superset of the content
From what you described earlier, it looked like you were looking for a
means to insert just a single "viewlet" into the page. That is, you were
looking to compose your view from multiple pieces, each piece being its
own, named, component. This is exactly what IContentProvider gives you.
If you don't need the logic that locates and renders multiple viewlets
inside a single "slot", then you're really after a simple content provider.
Another way to think about this is in terms of inversion-of-control. If
you write tal:replace="structure provider:foo", and "foo" is a simple
IContentProvider, then you're putting all control into the template. You
are asking for a particular, named component to be pulled in. If "foo"
is a viewlet manager, then you're just saying "here's a slot in my
template, do whatever you want in it". The viewlet manager
implementation is responsible for fiding the viewlets and rendering
them, and third party code can potentially register new viewlets
completely unbeknownst to your code.
To me, Grok could support "content providers" in a simple way by having
a base class (by comparison, there's no explicit ZCML directive to
create content providers as there is with viewlet managers and viewlets,
although a properly constructed named multi-adapter will of course
work). If you start out by having a content provider and you then want
to switch to something more pluggable - a viewlet manager - it's a
pretty easy refactoring.
> Viewlets with viewlet managers let you reuse the viewlets in any
> number of places,
In theory, yes, but if you use the <browser:viewlet /> directive, then
note that you explicitly list the viewlet manager (by interface) that
you want to plug into. Using a viewlet in more than one place requires
two registrations with the default viewlet manager implementation.
> by abstracting a layer between the viewlet and the
> view, and allowing viewlets to associate with any number of managers
> which themselves associate with views. This seems perfect for a
> general-purpose sort of system like Plone, where a single slot could
> be filled by six widgets, and a single widget could be inserted into
> six slots. But for my far less general-purpose app, what I find that
> I really want is to plug any or all of (X, Y, Z, ...) into A. In
> other words, I want any number of things to be "pluggably" inserted
> into a single template, but I don't need those things to be reused by
> other templates since my entry points are so specific.
> So I'm not exactly proposing viewlets without viewlet managers --
> rather, I'm proposing viewlets with *hidden* viewlet managers, where
> Grok handles all the details of those viewlet managers, and as far as
> the end user is concerned the viewlets are just being plugged directly
> into views in a decoupled, but not reusable, way.
I would be a bit cautious about this kind of magic. I don't really think
it's necessary, at least not if Grok made it easy to make content providers.
If you're talking about having a one-to-one mapping between the name you
invoke from your template (via the "provider:" expression type) and the
name you give a visual component, then you really want an
IContentProvider, not an IViewlet.
If you're talking about inverting the locus of control so that you just
declare a "slot" and you let other parts of the code worry about what
goes into it, then I think you want to make that explicit, with an
explicit viewlet manager.
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book
More information about the Grok-dev