20. Escribiendo Viewlets¶
Un viewlet para el comportamiento social¶
Un viewlet no es una vista, pero es un fragmento de HTML y la lógica Python que se puede colocar en varios lugares en el sitio. Estos lugares se llaman ViewletManager
.
Inspeccione y administre los viewlets existentes yendo a la dirección URL http://localhost:8080/Plone/@@manage-viewlets.
Ya hemos personalizado un viewlet (el archivo
collophon.pt
). Ahora agregamos un nuevo viewlet.Los viewlets no guardan los datos (los portlets si lo hacen).
Los viewlets no tienen interfaz de usuario (los portlets lo hacen).
Ejercicio 1¶
Registrar una viewlet number_of_talks
en el pie de página que es visible sólo para los administradores del sitio (el permiso que usted busca es cmf.ManagePortal
). Utilice sólo una plantilla (sin clase) para mostrar el número de charlas ya enviadas. Sugerencia: Utilice Aquisition para obtener al catálogo (Usted sabe, no debe hacer esto, pero hay un montón de código por ahí que lo hace...)
Solución
Registrar el viewlet en el archivo browser/configure.zcml
, agregando el siguiente código ZCML:
<browser:viewlet
name="number_of_talks"
for="*"
manager="plone.app.layout.viewlets.interfaces.IPortalFooter"
layer="zope.interface.Interface"
template="templates/number_of_talks.pt"
permission="cmf.ManagePortal"
/>
Para los parámetros for
y layer
el *
es la abreviatura de zope.interface.Interface
y el mismo efecto que la omisión de ellos: El viewlet se mostrará para todos los tipos de páginas y para todos los sitios de Plone en su instancia Zope.
Agregar el archivo de la plantilla browser/templates/number_of_talks.pt
, agregando el siguiente código HTML:
<div class="number_of_talks"
tal:define="catalog python:context.portal_catalog;
talks python:len(catalog(portal_type='talk'));">
There are <span tal:replace="talks" /> talks.
</div>
python:context.portal_catalog
devolverá el catálogo a través de la adquisición. Tenga cuidado si usted desea usar expresiones de rutas: content/portal_catalog
llama el catálogo (y devuelve todos los cerebros). Es necesario para evitar esto usando nocall:content/portal_catalog
.
Basándose en Adquisición es una mala idea. Sería mucho mejor utilizar la helper view llamada plone_tools
desde el módulo plone/app/layout/globals/tools.py
para obtener el catálogo.
<div class="number_of_talks"
tal:define="catalog context/@@plone_tools/catalog;
talks python:len(catalog(portal_type='talk'));">
There are <span tal:replace="talks" /> talks.
</div>
context/@@plone_tools/catalog
atraviesa a la vista plone_tools
y llama a su método catalog
. En expresiones Python debería verse así:
<div class="number_of_talks"
tal:define="catalog python:context.restrictedTraverse('plone_tools').catalog();
talks python:len(catalog(portal_type='talk'));">
There are <span tal:replace="talks" /> talks.
</div>
No es una buena práctica consultar el catálogo dentro de una plantilla, ya que incluso la simple lógica como esta debería vivir en Python. Pero es muy poderoso si está depurando o necesita una solución rápida y sucia.
Ejercicio 2¶
Registrar una viewlet days_to_conference
en la cabecera. Utilice una clase y una plantilla para mostrar el número de días hasta la conferencia. Usted consigue muchos puntos de bonificación si se muestra en un formato agradable (pensar “En 2 días” y “Último mes”) utilizando un Javascript existentes o biblioteca Python.
El viewlet social-viewlet¶
Vamos a añadir un enlace al sitio que utiliza la información que hemos recopilado utilizando el comportamiento social.
Registramos el viewlet en el archivo
browser/configure.zcml
, agregando el siguiente código ZCML:Esto registra un viewlet llamado
social
. Es visible en todos los contenidos que implementa la interfazISocial
de nuestro comportamiento. También es una buena práctica de obligar a la BrowserLayer llamadaIPloneconfSiteLayer
de nuestro complemento para que sólo sea mostrado si nuestro complemento esta instalado en realidad.La clase viewlet
SocialViewlet
se espera en un archivobrowser/viewlets.py
, agregando el siguiente código Python:Esta clase no hace nada excepto hacer que la plantilla asociada (Esa tenemos aún que escribirla)
Nota
Si utilizamos
Grok
no necesitaríamos registrar los viewlets en el archivoconfigure.zcml
pero si hay que hacerlo en código Python. Nos gustaría añadir un archivoviewlets.py
que contiene la clase viewlet, la cual se presenta a continuación:Esto haría lo mismo que el código anterior utilizando el paradigma de
Grok
de la convención sobre la configuración. En las browser views la referencia es llamadaview
, usted tenga en cuenta que en las viewlets Grok se llamaviewlets
(en ese casoviewlet/lanyrd_link
).Vamos a agregar el archivo de la plantilla restante
templates/social_viewlet.pt
.Como se puede ver esto no es un documento válido HTML. Eso no es necesario, porque no queremos una
view
completa aquí, sólo un fragmento de código HTML.Hay una sentencia
tal:define
, para la consulta view/lanyrd_link. Al igual en la page templates de la plantilla tiene acceso a su clase.Entonces, ahora tenemos que ampliar el Viewlet Social para añadir el atributo que le falta, agregando el siguiente código Python:
¿Por qué no acceder directamente contexto?
En este ejemplo,
ISocial(self.context)
devuelve el contexto directamente. Todavía es bueno utilizar este idioma por dos razones:Por lo tanto, en este ejemplo, usted puede simplemente escribir
return self.context.lanyrd
.Hasta ahora, hemos hecho: