Writing Viewlets#
In this part you will:
Display data from a behavior in a viewlet
Topics covered:
Viewlets
A viewlet for the featured behavior#
A viewlet is not a view but a snippet of HTML and logic that can be put in various places in the site.
These places are called viewletmanager
.
Inspect existing viewlets and their managers by going to http://localhost:8080/Plone/@@manage-viewlets.
We already customized a viewlet (
colophon.pt
). Now we add a new one.Viewlets don't save data (portlets do)
Viewlets have no user interface (portlets do)
Featured viewlet#
Let's add a link to the site that uses the information that we collected using the featured behavior.
We register the viewlet in browser/configure.zcml
.
1<browser:viewlet
2 name="featured"
3 for="ploneconf.site.behaviors.featured.IFeatured"
4 manager="plone.app.layout.viewlets.interfaces.IBelowContentTitle"
5 class=".viewlets.FeaturedViewlet"
6 layer="zope.interface.Interface"
7 template="templates/featured_viewlet.pt"
8 permission="zope2.View"
9 />
for
, manager
, layer
and permission
are constraints that limit the contexts in which the viewlet is loaded and rendered,
by filtering out all the contexts that do not match those constraints.
This registers a viewlet called featured
.
It is visible on all content that implements the interface IFeatured
from our behavior.
It is also good practice to bind it to a specific layer
, so it only shows up if our add-on is actually installed.
We will return to this in a later chapter.
The viewlet class FeaturedViewlet
is expected in a file browser/viewlets.py
.
1from plone.app.layout.viewlets import ViewletBase
2
3class FeaturedViewlet(ViewletBase):
4 pass
This class does nothing except rendering the associated template (That we have yet to write)
Let's add the missing template templates/featured_viewlet.pt
.
1<div id="featured">
2 <p tal:condition="python:view.is_featured">
3 This is hot news!
4 </p>
5</div>
As you can see this is not a valid HTML document. That is not needed, because we don't want a complete view here, a HTML snippet is enough.
There is a tal:define
statement, querying for view/is_featured
.
Same as for views, viewlets have access to their class in page templates, as well.
We have to extend the Featured Viewlet now to add the missing attribute:
1from plone.app.layout.viewlets import ViewletBase
2from ploneconf.site.behaviors.featured import IFeatured
3
4class FeaturedViewlet(ViewletBase):
5
6 def is_featured(self):
7 adapted = IFeatured(self.context)
8 return adapted.featured
So far, we
register the viewlet to content that has the IFeatured Interface.
adapt the object to its behavior to be able to access the fields of the behavior
return the link
Note
Why not to access context directly
In this example, IFeatured(self.context)
does return the context directly.
It is still good to use this idiom for two reasons:
It makes it clear that we only want to use the IFeatured aspect of the object
If we decide to use a factory, for example to store our attributes in an annotation, we would
not
get back our context, but the adapter.
Therefore in this example you could simply write return self.context.featured
.
Exercise 1#
Register a viewlet 'number_of_talks' in the footer that is only visible to admins (the permission you are looking for is cmf.ManagePortal
).
Use only a template (no class) to display the number of talks already submitted.
Hint: Use Acquisition to get the catalog (You know, you should not do this but there is plenty of code out there that does it...)
Exercise 2#
Register a viewlet 'days_to_conference' in the header. Use a class and a template to display the number of days until the conference.
You get bonus points if you display it in a nice format (think "In 2 days" and "Last Month") by using either JavaScript or a Python library.