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 interfazISocialde nuestro comportamiento. También es una buena práctica de obligar a la BrowserLayer llamadaIPloneconfSiteLayerde nuestro complemento para que sólo sea mostrado si nuestro complemento esta instalado en realidad.La clase viewlet
SocialViewletse 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
Grokno necesitaríamos registrar los viewlets en el archivoconfigure.zcmlpero si hay que hacerlo en código Python. Nos gustaría añadir un archivoviewlets.pyque 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
Grokde 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
viewcompleta 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: