15. Zope Page Templates¶
Plantillas de páginas son archivos HTML con alguna información adicional, escritas en TAL, METAL y TALES.
Las plantillas de página debe ser XML válido.
Los tres lenguajes son:
- TAL: “Template Attribute Language”
Plantillas XML / HTML usando con atributos especiales
Usando TAL nosotros podemos incluir expresiones en HTML
- TALES: “TAL Expression Syntax”
Define la sintaxis y la semántica de estas expresiones
- METAL: “Macro Expansion for TAL”
esto nos permite combinar, la reutilización y las plantillas anidadas juntas
TAL y METAL se escriben como atributos HTML (url, src, title). TALES están escritos como los valores de los atributos de HTML. Una declaración TAL típica tiene este aspecto:
<title tal:content="context/title">
The Title of the content
</title>
Se utiliza para modificar la salida:
<p tal:content="string:I love red">I love blue</p>
resultado en:
<p>I love red</p>
Vamos a intentarlo. Abra el archivo demoview.pt
y agregue:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
i18n:domain="ploneconf.site">
<body>
<p>red</p>
</body>
</html>
TAL y TALES¶
Vamos a añadir un poco de magia y modificar la etiqueta <p>:
<p tal:content="string:blue">red</p>
Esto resultará en el siguiente código HTML:
<p>blue</p>
Sin reiniciar Plone abra en el navegador http://localhost:8080/Plone/@@demoview.
Lo mismo ocurre con los atributos. Remplace en la línea <p> con el siguiente código:
<a href="http://www.mssharepointconference.com"
tal:define="a_fine_url string:http://www.ploneconf.org"
tal:attributes="href a_fine_url"
tal:content="string:A even better conference">
A sharepoint conference
</a>
resultado en:
<a href="http://www.ploneconf.org">
A even better conference
</a>
Nosotros hemos utilizado los tres atributos TAL aquí. Esta es la lista completa de los atributos TAL:
tal:define
definir las variables. Nosotros definimos la variable url para la cadena “http://www.ploneconf.org“
tal:content
reemplazar el contenido de un elemento. Hemos sustituido el valor por defecto de contenido con algunas como “A even better conference”
tal:attributes
cambiar dinámicamente atributos de los elementos. Nosotros hemos establecido el atributo href html a la variable
a_fine_url
tal:condition
pruebas, si la expresión es verdadera o falsa.
tal:repeat
repite un elemento iterable, en nuestro caso, la lista de charlas.
tal:replace
reemplazar el contenido de un elemento como
tal:content
, pero se elimina el elemento sólo dejando el contenido.tal:omit-tag
eliminar un elemento, dejando el contenido del elemento.
tal:on-error
controlar los errores.
Expresiones Python¶
Hasta ahora sólo utilizamos una expresión TALES (el bit string:
). Usemos una expresión TALES diferente ahora. Con python:
podemos usar código python. Un ejemplo sencillo:
<p tal:define="title context/title"
tal:content="python:title.upper()">
A big title
</p>
Y otro ejemplo:
<p tal:define="talks python:['Dexterity for the win!',
'Deco is the future',
'A keynote on some weird topic',
'The talk that I did not submit']"
tal:content="python:talks[0]">
A talk
</p>
Con expresiones python
sólo se puede escribir declaraciones individuales
usted podría importar cosas pero no debe (ejemplo:
tal:define="something modules/Products.PythonScripts/something;
).
tal:condition¶
tal:condition
pruebas, si la expresión es verdadera o falsa.
Si es true, entonces la etiqueta se representa.
Si es false, entonces la etiqueta y todos sus hijos se retiran y ya no se evalúa.
Podemos invertir la lógica anteponiendo un
not:
a la expresión.
Vamos a añadir otro atributo TAL para nuestro ejemplo anterior:
tal:condition="talks"
También pudimos probar que el número de charlas:
tal:condition="python:len(talks) >= 1"
o si una cierta charla está en la lista de charlas:
tal:condition="python:'Deco is the future' in talks"
tal:repeat¶
Probemos otra sentencia:
<p tal:define="talks python:['Dexterity for the win!',
'Deco is the future',
'A keynote on some weird topic',
'The talk that I did not submit']"
tal:repeat="talk talks"
tal:content="talk">
A talk
</p>
tal:repeat
repite un elemento iterable, en nuestro caso, la lista de charlas.
Cambiamos el formato un poco para construir una lista en la que hay una lista <li>
para cada charla:
<ul tal:define="talks python:['Dexterity for the win!',
'Deco is the future',
'A keynote on some weird topic',
'The talk that I did not submit']">
<li tal:repeat="talk talks"
tal:content="talk">
A talk
</li>
<li tal:condition="not:talks">
Sorry, no talks yet.
</li>
</ul>
Expresiones de rutas¶
En cuanto TALES hasta ahora hemos utilizado la string:
o python:
o sólo las variables. La expresión siguiente y más comunes son de path-expressions. Opcionalmente se puede iniciar path-expression con el path:
Cada expresión de ruta comienza con un nombre de variable. Puede ser tanto un objeto como context
, view
, template
o una variable definida anteriormente como charla
.
Después de la variable se añade una barra /
y el nombre de un sub-objeto, atributo o método invocable. El carácter ‘/’ se utiliza para terminar el nombre de un objeto y el inicio del nombre de la propiedad. Mismas propiedades pueden ser objetos que a su vez tienen propiedades.
<p tal:content="context/title"></p>
Nos puede encadenar varios de los elementos para obtener la información que queremos.
<p tal:content="context/REQUEST/form"></p>
Esto devolverá el valor de la forma de diccionario del objeto HTTPRequest. Útil para la forma de manipulación.
El carácter |
(operador lógico “o”) se utiliza para encontrar un valor alternativo a un camino si la primera ruta se evalúe como nothing
o no existe.
<p tal:content="context/title | context/id"></p>
Esto devuelve el id del contexto si no tiene título.
<p tal:replace="talk/average_rating | nothing"></p>
Esto devuelve nada si no hay ‘average_rating’ para una charla. Lo que no funciona es tal:content="python:talk['average_rating'] or ''"
. ¿Quién sabe lo que esto produciría?
Conseguiremos KeyError: 'average_rating'
. Es muy mala práctica, use el carácter |
con demasiada frecuencia, ya que se tragará errores como un error tipográfico en tal:content="talk/averange_ratting | nothing"
y es posible que se preguntan por qué no existen calificaciones más tarde...
No puede y no debe utilizarlo para evitar errores como un bloque try / except.
Hay varias variables incorporado que se pueden utilizar en caminos:
El más utilizado es nothing
que es el equivalente a None
<p tal:replace="nothing">
this comment will not be rendered
</p>
Un diccionario de todas las variables disponibles es CONTEXTS
<dl tal:define="path_variables_dict CONTEXTS">
<tal:vars tal:repeat="variable path_variables_dict">
<dt tal:content="variable"></dt>
<dd tal:content="python:path_variables_dict[variable]"></dd>
</tal:vars>
</dl>
Muy útil para depuración :-)
Puro bloques TAL¶
Podemos utilizar atributos TAL sin marcas HTML. Esto es útil cuando no es necesario añadir las etiquetas para el marcado
Sintaxis:
<tal:block attribute="expression">some content</tal:block>
Ejemplos:
<tal:block define="id template/id">
...
<b tal:content="id">The id of the template</b>
...
</tal:block>
<tal:news condition="python:context.content_type == 'News Item'">
This text is only visible if the context is a News Item
</tal:news>
Manejo de datos complejos en plantillas¶
Vamos a pasar a un poco más complejo de datos. Y a otro atributo TAL:
- tal:replace
reemplazar el contenido de un elemento y elimina el elemento dejando sólo el contenido.
Ejemplo:
<p>
<img tal:define="tag string:<img src='https://plone.org/logo.png'>"
tal:replace="tag">
</p>
este resulta en:
<p>
<img src='https://plone.org/logo.png'>
</p>
tal:replace
cae su propia base de etiquetas a favor del resultado de la expresión TALES. Por lo tanto el original <img... >
se sustituye. Pero el resultado se escapó por defecto.
Para prevenir que se escapen utilizamos structure
<p>
<img tal:define="tag string:<img src='https://plone.org/logo.png'>"
tal:replace="structure tag">
</p>
Ahora vamos a emular una estructura típica Plone mediante la creación de un diccionario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <table tal:define="talks python:[{'title':'Dexterity for the win!',
'subjects':('content-types', 'dexterity')},
{'title':'Deco is the future',
'subjects':('layout', 'deco')},
{'title':'The State of Plone',
'subjects':('keynote',) },
{'title':'Diazo designs dont suck!',
'subjects':('design', 'diazo', 'xslt')}
]">
<tr>
<th>Title</th>
<th>Topics</th>
</tr>
<tr tal:repeat="talk talks">
<td tal:content="talk/title">A talk</td>
<td tal:define="subjects talk/subjects">
<span tal:repeat="subject subjects"
tal:replace="subject">
</span>
</td>
</tr>
</table>
|
Nosotros emulamos una lista de charlas y mostrar información en una tabla. Nos pondremos en contacto a la lista de las charlas más tarde, cuando se utilizan los verdaderos objetos charlas que hemos creado con dexterity.
Para completar la lista que aquí están los atributos TAL que no hemos utilizado todavía:
tal:omit-tag
Omite las etiquetas de los elementos, dejando sólo el contenido interno.
tal:on-error
controlar los errores.
Cuando un elemento tiene múltiples sentencias, se ejecutan en este orden:
- define
- condition
- repeat
content o replace
- attributes
- omit-tag
METAL y macros¶
¿Por qué nuestra vista es tan feo?, ¿Cómo conseguimos nuestro HTML para representar en la interfaz de usuario de Plone?
Utilizamos METAL (extensión macro para TAL) para definir ranuras que podemos llenar y macros que podemos reutilizar.
Agregamos a la etiqueta <html>
:
metal:use-macro="context/main_template/macros/master"
Y a continuación, ajustar el código que queremos poner en el área de contenido de Plone en:
<metal:content-core fill-slot="content-core">
...
</metal:content-core>
Esto pondrá a nuestro código de una sección definida en el main_template llamado “content-core”.
Ahora la plantilla debería tener el siguiente aspecto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="ploneconf.site">
<body>
<metal:content-core fill-slot="content-core">
<table tal:define="talks python:[{'title':'Dexterity for the win!',
'subjects':('content-types', 'dexterity')},
{'title':'Deco is the future',
'subjects':('layout', 'deco')},
{'title':'The State of Plone',
'subjects':('keynote',) },
{'title':'Diazo designs are great',
'subjects':('design', 'diazo', 'xslt')}
]">
<tr>
<th>Title</th>
<th>Topics</th>
</tr>
<tr tal:repeat="talk talks">
<td tal:content="talk/title">A talk</td>
<td tal:define="subjects talk/subjects">
<span tal:repeat="subject subjects"
tal:replace="subject">
</span>
</td>
</tr>
</table>
</metal:content-core>
</body>
</html>
|
Nota
Desde la vista demoview solamente es utilizada el contenido de la plantilla, no por el contexto que le toca no tiene mucho sentido tener la barra de edición. Nos lo ocultamos estableciendo la variable correspondiente en el request actual con el python a 1: request.set('disable_border', 1)
.
La manera más fácil de hacer esto es definir una variable dummy. Dummy porque nunca se usa, salvo que nos permita ejecutar algún código.
<metal:block fill-slot="top_slot"
tal:define="dummy python:request.set('disable_border', 1)" />
Macros en browser-views¶
Define un macro en un nuevo archivo macros.pt
<div metal:define-macro="my_macro">
<p>I can be reused</p>
</div>
Registrarlo como un BrowserView (esta vez sin una clase Python) en sentencias ZCML:
<browser:page
for="*"
name="ploneconf.site.macros"
template="templates/macros.pt"
permission="zope2.View"
/>
Reuse el macro en la plantilla demoview.pt
:
<div metal:use-macro="view/context/@@ploneconf.site.macros/my_macro">
Instead of this the content of the macro will appear...
</div>
Accediendo a Plone desde la plantilla¶
En nuestra plantilla tenemos acceso al objeto de contexto en el que la vista se llama en adelante, la propia browser-views (es decir, todos los métodos de python vamos a poner en el punto de vista más adelante), los objetos request y response y con ellas podemos conseguir casi cualquier cosa.
En las plantillas también podemos acceder a otras browser-views. Algunos de los que existen para facilitar el acceso a los métodos que a menudo necesitamos:
tal:define="context_state context/@@plone_context_state;
portal_state context/@@plone_portal_state;
plone_tools context/@@plone_tools;
plone_view context/@@plone;"
@@plone_context_state
El BrowserView
plone.app.layout.globals.context.ContextState
tiene métodos útiles que tienen que ver con el objeto de contexto actual comois_default_page
@@plone_portal_state
El BrowserView
plone.app.layout.globals.portal.PortalState
tiene métodos para el portal comoportal_url
@@plone_tools
El BrowserView
plone.app.layout.globals.tools.Tools
da acceso a las herramientas más importante como elplone_tools/catalog
Estos son muy utilizados y hay muchos más.
Lo que echamos de menos¶
Hay algunas cosas que no nos cubrimos hasta el momento:
tal:condition="exists:expression"
comprueba si existe un objeto o un atributo (rara vez utilizada)
tal:condition="nocall:context"
que explícitamente no llamar a un método invocable.
Si nos referimos a objetos de contenido sin usar el modificador nocall: estos objetos son innecesariamente representados en la memoria como la expresión se evaluada.
i18n:translate
yi18n:domain
las cadenas que ponemos en las plantillas se pueden traducir de forma automática.
Hay mucho más acerca de TAL, TALES y METAL que no hemos cubierto. Usted solamente aprenderá si sigues leyendo, escribiendo y personalización de plantillas.
Ver también
- http://docs.plone.org/4/en/adapt-and-extend/theming/templates_css/template_basics.html
Usando Zope Page Templates: http://docs.zope.org/zope2/zope2book/ZPT.html
Referencia de Zope Page Templates: http://docs.zope.org/zope2/zope2book/AppendixC.html
Chameleon¶
Chameleon es el sucesor de TAL y serán incorporado en Plone 5.
Plip para Chameleon: https://dev.plone.org/ticket/12198
Página principal: http://www.pagetemplates.org/
Capa de Integración para Plone: five.pt
En Plone 4 nosotros usaremos ZPT por defecto.