Aggiungere una viewlet
medio
Un buon punto di partenza è guardare uno degli esempi che accompagnano DIYPloneStyle (nella versione 3.0, ancora in beta, ma già usabile) per meglio capire il meccanismo: il prodotto credits_viewlet, localizzato in DIYPloneStyle/example/, aggiunge una nuova viewlet nel pié di pagina.
Nella cartella browser/ di credits_viewlet vi sono diversi file:
- browser/ - __init__.py - configure.zcml - interfaces.py - logo.pt - viewlets.py
__init__.py
Un file vuoto che serve solo a rendere browser un modulo Python.
configure.zcml
Contiene le configurazioni Zope 3 per browser.
interfaces.py
L'utilizzo di questo file verrà spiegato successivamente.
logo.pt
Il template che rimpiazzerà il codice HTML contenuto nel main_template.
viewlets.py
Contiene le classi Python delle viewlet.
Sempre nella cartella DIYPloneStyle/example/credits_viewlet vi è profiles/, che contiene i file di configurazione per Generic Setup: skins.xml e viewlets.xml.
Pratica
Registrazione della viewlet
Ora possiamo riprodurre quest'esempio nel nostro prodotto MyTheme.
Per creare una nuova viewlet bisogna scriverne la classe MyTheme/browser/viewlets.py (che renderizza il template MyTheme/browser/credits.pt) e registrarla (in nel MyTheme/browser/configure.zcml) nel viewlet manager da cui vogliamo sia mostrata, per poi posizionarla dove desiderato (in MyTheme/profiles/default/viewlets.xml).
Nota
Se si genera il proprio prodotto con DIYPloneStyle, si deve usare l'opzione --add-viewlet-example richiamando lo script che genera il modello per includere il codice della viewlet di esempio. Il plone3_theme di ZopeSkel include di default il codice di base della viewlet.
E' necessario creare il file vuoto MyTheme/browser/__init__.py per rendere browser/ un package Python.
Modificando MyTheme/browser/viewlets.py otteniamo:
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.app.layout.viewlets.common import ViewletBase
DESIGNER = 'John Doe'
class CreditsViewlet(ViewletBase):
render = ViewPageTemplateFile('credits.pt')
def update(self):
# set here the values that you need to grab from the template.
# stupid example:
self.designer = DESIGNER In MyTheme/browser/credits.pt:
<div id="design-credits" i18n:domain="custom_i18n_domain"> <span i18n:translate="design_by">Design by: <span tal:omit-tag="python:True" tal:content="view/designer" i18n:name="designer">Terry Gilliam</span>.</span> </div>
In MyTheme/browser/configure.zcml:
<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="custom_i18n_domain"> <browser:viewlet name="example.credits" manager="plone.app.layout.viewlets.interfaces.IPortalFooter" class=".viewlets.CreditsViewlet" permission="zope2.View" /> </configure>
In MyTheme/profiles/default/viewlets.xml:
<?xml version="1.0"?> <object> <order manager="plone.portalfooter" skinname="Credits Viewlet Theme" based-on="Plone Default"> <viewlet name="example.credits" insert-before="plone.colophon" /> </order> </object>
Infine si registra il nuono skin in MyTheme/profiles/default/skins.xml:
<?xml version="1.0"?> <object name="portal_skins"> <skin-path name="Credits Viewlet Theme" based-on="Plone Default" /> </object>
Ora è possibile riavviare Zope ed installare il nuovo prodotto.
Sarà quindi possibile vedere che il footer del portale Plone è stato modificato e che ora mostra un messaggio indicante il detentore dei diritti sul design del sito.
Skin layer
E' importante notare che andando come amministratore nel Pannello di controllo, poi in Temi, e lì selezionando il Plone Default come tema, la viewlet credits continua ad essere mostrata.
Bisogna perciò far si che questa viewlet sia mostrata solo nello skin per cui è stata progettata. Si potrebbe nasconderla agli altri temi usando il nodo <hidden /> nel file viewlets.xml, ma ciò non sarebbe adatto ad un prodotto da distribuire in quanto non si possono conoscere tutti gli altri temi usati nei portali in cui potrebbe essere installato.
Per fortuna è possibile registrare una viewlet per un unico skin grazie al package plone.theme, che ci permette di impostare uno skin layer di Zope 3 corrispondente alla selezione di uno skin in portal_skins.
In MyTheme/browser/interfaces.py:
from zope.publisher.interfaces.browser import IDefaultBrowserLayer class IMyThemeSpecific(IDefaultBrowserLayer): """Marker interface that defines a Zope 3 skin layer. It will be used for the viewlets that we want to add to the "My Theme" skin only. """
E in MyTheme/browser/configure.zcml:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<interface
interface=".interfaces.IThemeSpecific"
type="zope.publisher.interfaces.browser.IBrowserSkinType"
name="My Theme"
/>
<browser:viewlet
name="example.credits"
manager="plone.app.layout.viewlets.interfaces.IPortalFooter"
class=".viewlets.CreditsViewlet"
permission="zope2.View"
layer=".interfaces.IThemeSpecific"
/>
</configure> Si consiglia di porre attenzione alla dichiarazione dell'interfaccia dello skin layer di Zope 3 e ai parametri per la viewlet stessa.
Il parametro name nella dichiarazione dell'interfaccia deve essere lo stesso di quello del tema, come è possibile vedere nel Pannello di Controllo > Temi.
L'attributo layer della dichiarazione della viewlet deve essere l'interfaccia utilizzata per definire lo skin layer.
Dopo il riavvio di Zope o il refresh del prodotto, e ovviamente il ricaricamento della pagina, è possibile vedere che il tema Plone Default non mostra più la nostra viewlet.
