Skin, Componentes, Configuración. Los tres bloques para construcción principales de un tema; interconectados, pero cada con un tipo distinto de comportamiento.
Revisión general de los bloques para construcción y la forma en que se unen para crear un tema.
En realidad, hay tres elementos principales en un tema. El siguiente diagrama le muestra cómo estas ranuras se comportan en conjunto:
Plantillas, hojas de estilo, archivos Javascript, el modo de personalizarlos, dónde encontrarlos.
Plantillas y el lenguaje de plantillas
Los elementos principales de un skin son las plantillas de página, imágenes, scripts de Python, archivos CSS, y archivos JavaScript.
Las plantillas de página (archivos .pt o ZPT) son una parte esencial de un tema Plone y probablemente es el aspecto más fácil de dominar en Plone. Están escritos en un lenguaje elegante de plantillas base-XML llamado TAL, a veces hacen uso de macros (METAL), y en ocasiones incorporan expresiones Python (cálculos pequeños de una línea) o scripts de Python.
Hay varias introducciones excelentes para ZPT, y no se necesita mucho tiempo para aprender TAL. Pruebe estas:
TAL es el único idioma que realmente recomendamos para que aprenda correctamente. Para el resto puede escoger su camino o familiarizarse a medida que avanza.
Una página Web Plone se realiza mediante la agregación de plantillas, en lugar de una sola, y hay un par de aspectos de las Plantillas de página Zope que tendrá que tener en cuenta.
Una ranura es una sección de una plantilla predefinida. Esta puede dejarse vacía, o darle un contenido por defecto, pero está disponible para ser llenada en el momento. Un ranura está definida en una plantilla con un código como este:
<metal:bodytext metal:define-slot="main" tal:content="nothing">
.....
</metal:bodytext>
Y llenada a través de otra plantilla como esta:
<metal:main fill-slot="main">
<h1 class="documentFirstHeading">
......
</h1>
</metal:main>
El tutorial ZPT en plone.org le guía a través de esto con más detalle, y la sección Plantillas y componentes para páginas de este manual le muestra un ejemplo.
Nota
el término “vista” también tiene una aplicación más técnica, por lo que en el contexto de los Componentes (descrito posteriormente en este manual) va a significar algo diferente.
Desde la perspectiva del usuario, contribuyente, o la del visitante, una vista es la forma en que un elemento de contenido es presentado en la página. Hay una útil introducción a este tema en el manual de usuario de Plone.
la plantillas que se utilizan para representar un elemento de contenido para una vista poseen _view anexadas a sus nombres (ej., document_view.pt) y pueden tener un título como “Standard View” (Vista estándar) Estas plantillas en realidad so un conjunto de información a punto de encajar en ranuras.
Se trata de pequeñas funciones independientes para los momentos en que necesita unas pocas líneas de código para realizar el cálculo. En el sistema de archivos poseen una extensión .py; Los encontrará en la Interfaz de Administración de Zope como Script (Python).
He aquí un fragmento de la plantilla event_view (la vista de contenido para el tipo de contenido evento), la cual utiliza un script de Python para dar formato al campo de tiempo de acuerdo con el formato predeterminado para el sitio. Si busca en CMFPlone/skins/plone_scripts, encontrará el toLocalizedTime.py; sólo unas pocas líneas de código.
<span metal:define-slot="inside"
class="explain"
tal:attributes="title python:here.end()"
tal:content="python:*here.toLocalizedTime*(here.end(),
long_format=1)">End Date Time</span>
Las Plantillas de página son una herramienta de generación de páginas Web. En esta parte, revisaremos los fundamentos y mostraremos cómo utilizarlos en su sitio Web para crear páginas Web dinámicas fácilmente.
El objetivo de las Plantillas de página es flujo de trabajo natural. un diseñador usará un editor HTML WYSIWYG (del inglés What You See Is What You Get que se traduce como “Lo que ves es lo que obtienes”) para crear una plantilla, luego un programador lo editará para que forme parte de una por el programador, él no va a alterar la aplicación. aplicación. Si es requerido, el diseñador puede cargar la plantilla de nuevo dentro de su editor y realizar más cambios en su estructura y apariencia. A través medidas razonables para preservar los cambios realizados
Las plantillas de páginas apuntan a este objetivo mediante la adopción de tres principios:
Una Plantilla de página es como un modelo de páginas que se generará. En particular es una página valida HTML/XHTML. Puesto que HTML es altamente estructurado, y los editores WYSIWYG cuidadosamente preservan esta estructura, hay límites estrictos en la forma en que el programador puede cambiar una página y seguir respetando el primer principio
A pesar de que las Plantillas de página son adecuadas para programadores y diseñadores que necesitan trabajar juntos para crear páginas web dinámicas construyendo la base para la mayoría de páginas Plone, usted igualmente debería aprender al menos un poco sobre esto si es necesario personalizar el aspecto de Plone o el diseño. Además, puede ser más sencillo de usarlas y entenderlas que la alternativa DTML (Lenguaje de Marcado de Documento de Plantilla).
Hay una gama de sistemas de plantillas en el mercado, algunas de ellas populares como ASP, JSP, y PHP. Desde el principio, Zope siempre ha integrado un lenguaje de plantilla llamado DTML. ¿Por qué inventar otro?
En primer lugar ninguno de estos sistemas de archivos están dirigidos a diseñadores de HTML. Una vez que una página se ha convertido en una plantilla, no es HTML válido, por lo que es difícil trabajarla fuera de la aplicación. Cada uno de ellos viola el primer o segundo principio de Plantillas de página de Zope en cierto grado u otro. Los programadores no deberían “secuestrar” el trabajo de los diseñadores y convertir el HTML en software. XMCL, parte del proyecto Enhydra, comparte nuestro objetivo, pero requiere que el programador escriba cantidades considerables de código de soporte Java para cada plantilla.
En segundo lugar, todos estos sistemas sufren con respecto a la separación entre presentación, lógica y contenido (datos). Sus violaciones del tercer principio disminuyen la escalabilidad de la administración de contenidos y los esfuerzos de desarrollo de sitios Web que utilizan estos sistemas.
Las Plantillas de página usan Template Attribute Language (TAL) (Lenguaje de Atributo de Plantillas). TAL consiste en atributos especiales de etiquetas, por ejemplo, el título de una página dinámica puede lucir como este:
<title tal:content="context/title">Page Title</title>
El atributo tal:content es una sentencia TAL. Debido a que tiene un namespace XML (la parte tal:) la mayoría de herramientas de edición no se quejarán por no entenderlo, y no lo eliminarán. No cambiará la estructura o apariencia de la plantilla cuando se carga en el editor WYSIWYG o en un navegador Web. El nombre content (contenido) indica que definirá el contenido de la etiqueta title (título), y el valor “context/title” es una expresión que provee el texto a insertar en la etiqueta
Para el diseñador HTML que usa una herramienta WYSIWYG, esto es HTML perfectamente válido, y se muestra en el editor de la manera en que un título debería verse. El diseñador que no preocupa por los detalles de aplicación de TAL, sólo ve una * maqueta * de la plantilla dinámica, con valores ficticios como “Page Title” (Título de página) para el título del documento.
Cuando esta plantilla se guarda en Zope y es vista por un usuario, Zope convierte este contenido estático en contenido dinámico y reemplaza “Page Title”, con lo que sea que “context/title” resuelva. En este caso, “context/title” se resuelve en el título del objeto para el cual se aplica la plantilla. Esta sustitución se realiza de forma dinámica, cuando la plantilla se ve.
Este ejemplo demuestra también el segundo principio. Cuando usted ve la plantilla en un editor, el texto del título actuará como un marcador de posición para el texto del título dinámico, la plantilla proporciona un ejemplo de cómo los documentos generados se verán.
Hay comandos de plantilla para la sustitución de etiquetas completas, su contenido, o sólo algunos de sus atributos. Usted puede repetir una etiqueta varias veces u omitirla por completo. Puede unir partes de varias plantillas, y especificar el tratamiento de errores simples. Todas estas funciones son usadas para generar estructuras de documentos, usted no puede crear subrutinas o clases, escribir bucles o pruebas multi-modo, o fácilmente expresar algoritmos complejos. Para estas tareas, utilice Python.
El lenguaje de plantillas deliberadamente no es tan poderoso y objetivo- general como podría ser. Está destinado a ser utilizado dentro de un marco (como Zope) en el que otros objetos manejan la lógica de negocio y aquellas tareas no relacionadas con el diseño de la página.
Por ejemplo, el lenguaje de plantillas será ventajoso para renderizar una página de factura, al generar una fila para cada elemento, e insertar la descripción, cantidad, precio, y otros para el texto de cada fila. No se pude utilizar para crear el registro de la factura en una base de datos o para interactuar con un centro de procesamiento de tarjetas de crédito.
Si usted diseña páginas, probablemente use FTP o WebDAV en vez de la Interfaz de Administración de Plone (ZMI) para crear y editar Plantillas de páginas, o desarrolla plantillas en el filesystem para su posterior instalación. Si usted no es el dueño del sitio Zope, pregunte a su administrador Zope por instrucciones, pero para los pequeños ejemplos mostrados en este artículo, es mucho más sencillo usar la ZMI. Para más información sobre el uso de FTP o WebDAV con Zope, vea The Zope Book (el Libro de Zope) o el artículo WebDAV de Jeffrey Shell.
También puede usar Emacs, cadaver, o algún otro cliente, pero si usted es un programador o administrador de Zope, lo más seguro es que use la ZMI de igual manera, al menos ocasionalmente. Revise el Libro de Zope para instrucciones sobre la configuración de este para que trabaje con varios clientes.
Use su navegador Web para entrar en la Interfaz de Administración de Zope como lo haría normalmente con Zope. Escoja una carpeta (root está bien) y seleccione “Page Template” (Plantilla de página) de la lista desplegable. Escriba “simple_page” en el campo de Id del formulario para agregar, luego pulse el botón “Agregar y Editar”.
Ahora debería ver la página principal de edición para la nueva Plantilla de página. El título está en blanco, el tipo-contenido es text/html, y el texto de la plantilla por defecto está en el área de edición.
Ahora creará una página dinámica muy simple. Escriba las palabras “Simple Page” (página simple) en el campo de Título. Luego edite el cuerpo de texto de la plantilla para que luzca como este:
This is <b tal:replace="template/title">the Title</b>.
Ahora presione el botón de guardar cambios, y la página de edición debería mostrar un mensaje confirmando que los cambios han sido guardados. Si un mensaje de error aparece en la parte de arriba del área de código, o algún texto que comienza con <-- Page Template Diagnostics (diagnóstico de plantilla de página) se ha añadido a la plantilla, entonces revise que escribió el ejemplo correctamente y guárdelo nuevamente. No necesita borrar el comentario de error, ya que una vez que este haya sido corregido desaparecerá.
Haga clic en la pestaña Test (Prueba). debería ver una página casi completamente vacía con “This is a simple Page” (Esto es una página simple) en la parte superior.
Respalde, y haga clic en el enlace “Browse HTML source” (Examinar fuente HTML) bajo el campo de tipo-contenido. Esto le mostrará la fuente no renderizada o procesada de la plantilla. debería ver “This is (Esto es) the Title (el título).” retorne nuevamente, para que así este listo para editar más aún el ejemplo.
El texto “template/title” (plantilla/título) en su simple Plantilla de página es una expresión de ruta. Este el tipo más común de expresiones definidas por la Sintaxis de Expresiones TAL (TALES). Manda a buscar la propiedad del título de la plantilla. Aquí hay otras expresiones comunes de ruta:
Cada ruta comienza con una nombre variable. Si la variable contiene el valor que usted quiere, deténgase allí. Caso contrario, agregue una barra (/) y el nombre de un sub-objeto o propiedad. Es posible que tenga que pasar a través de varios sub-objetos para llegar al valor que usted está buscando.
Hay una construcción pequeña en un conjunto de variables tales como request (solicitud) y user (usuario), que serán listados y descritos posteriormente, y también aprendió a cómo definir sus propias variables.
En su plantilla “simple_page”, utilizó la sentencia tal:replace en una etiqueta en negrita. Cuando la probó, esta remplazó la etiqueta completa por el título de la plantilla. Por otra parte cuando examinó el código, vio el texto de la plantilla en negrita. Nosotros hemos utilizado una etiqueta en negrita para resaltar la diferencia.
Con el fin de colocar el texto dinámico dentro de otro texto, se suele usar tal:replace en una etiqueta span (lapso). Agregue las líneas siguientes a su ejemplo:
<br>
The URL is <span tal:replace="request/URL">URL</span>.
La etiqueta span es estructural, no visual, así que esta luce como “The URL is URL.” (La URL es URL), cuando vea el código en un editor o navegador. Cuando vea la versión renderizada, esta puede lucir a algo como esto:
<br>
The URL is http://localhost:8080/simple_page.
Recuerde que tiene que tener cuidado cuando este editando y no destruir el span o ingresar etiquetas de formato tales como b o fuente dentro de este, ya que también serán remplazadas.
Si quiere insertar texto en una etiqueta sin modificarla como tal, use tal:content. Para definir el título de su página de prueba al título de propiedad de la plantilla, agregue las líneas siguientes encima del otro texto:
<head>
<title tal:content="template/title">The Title</title>
</head>
Si usted abre la pestaña Test en una nueva ventana, el título que tendrá la ventana será “a Simple Page” (una página simple).
Ahora agregará contexto a su página, en la forma de una lista de objetos almacenados en la misma carpeta. Creará una tabla que una fila numerada para cada objeto, y columnas para el ID, meta-type, y título. Agregue estas líneas a la parte inferior de su plantilla:
<table border="1" width="100%">
<tr>
<th>#</th><th>Id</th><th>Meta-
Type</th><th>Title</th>
</tr>
<tr tal:repeat="item container/objectValues">
<td tal:content="repeat/item/number">#</td>
<td tal:content="item/id">Id</td>
<td tal:content="item/meta_type">Meta-Type</td>
<td tal:content="item/title">Title</td>
</tr>
</table>
La sentencia tal:repeat en la fila de tabla se traduce en “repita esta fila para cada elemento en mi lista contenedora de valores de objetos”. Repetir la sentencia coloca los objetos de la lista dentro de la variable del elemento uno a la vez, y hace una copia de la fila usando esa variable. El valor de “item/id” en cada fila es la ID del objeto para esa fila.
Puede usar cualquier nombre que le parezca para la variable del item (elemento), siempre y cuando comience con una letra y contenga sólo letras, números, y subguiones (_). Esta sólo existe en la etiqueta <tr> tag; si la trata de usar por encima o por debajo de esa etiqueta obtendrá un error.
También puede usar el nombre de la variable tal:repeat para obtener información sobre la repetición actual. Colocándola después de la variable incorporada repetida en una ruta, puede acceder a la cuenta de repetición comenzando a partir de cero (index), de uno (number), de “A” (Letter), y de otras maneras. De esta manera la expresión repeat/item/number será 1 en la primera fila, 2 en la segunda fila, y así sucesivamente.
Ya que un bucle tal:repeat puede colocarse dentro de otro, más de uno puede estar activo al mismo tiempo. Por esta razón debe escribir repeat/item/number en vez de repeat/number. Usted debe especificar el bucle por el que está interesado incluyendo el nombre de este.
Vea la plantilla, y se dará cuenta de que la tabla es muy sobria. Vamos a mejorarla dándole sombra a ciertas filas. Copia de la segunda fila de la tabla, luego edite el código para que se vea así:
<table border="1" width="100%">
<tr>
<th>#</th><th>Id</th><th>Meta-
Type</th><th>Title</th>
</tr>
<tbody tal:repeat="item container/objectValues">
<tr bgcolor="#EEEEEE"
tal:condition="repeat/item/even">
<td tal:content="repeat/item/number">#</td>
<td tal:content="item/id">Id</td>
<td tal:content="item/meta_type">Meta-
Type</td>
<td tal:content="item/title">Title</td>
</tr>
<tr tal:condition="repeat/item/odd">
<td tal:content="repeat/item/number">#</td>
<td tal:content="item/id">Id</td>
<td tal:content="item/meta_type">Meta-
Type</td>
<td tal:content="item/title">Title</td>
</tr>
</tbody>
</table>
La tal:repeat no ha cambiado, simplemente la ha movido a la nueva etiqueta tbody. Esta es una etiqueta HTML estándar destinada a agrupar las filas del cuerpo de una tabla, que es la manera en que las está utilizando. Hay dos filas en el cuerpo con columnas idénticas, y una tiene un fondo gris.
Si ve el código de la plantilla, verá dos filas. Si usted no hubiera agregado la sentencia tal:condition a la filas, la plantilla generaría ambas filas para cada elemento, que es algo que usted no quiere. La sentencia tal:condition en la primera fila asegura que sólo sea agregada en repeticiones de indexación-par, mientras que la segunda condición sólo le permite aparecer en repeticiones de indexación-impar.
Una sentencia tal:condition no hace nada si su expresión tiene un valor verdadero, pero elimina la etiqueta de declaración en su totalidad, incluyendo su contenido, si el valor es falso. Las propiedades par e impar de repeat/item son cero o uno. El número cero, una cadena en blanco, una lista vacía, y la variable integrada nothing (nada) son todos valores falsos. Casi cualquier otro valor es verdadero, otros números a parte del cero, y cadenas con cualquier cosa dentro de ellas (¡incluso espacios!).
La plantilla mostrará siempre al menos una fila, ya que la propia plantilla es uno de los objetos listados. En otras circunstancias, puede existir la posibilidad de que quiera que la tabla este vacía. Supongamos que usted quiere en este caso, omitir toda la tabla. Esto lo puede hacer agregando tal:condition a la tabla:
<table border="1" width="100%"
tal:condition="container/objectValues">
Ahora cuando no haya objetos, ninguna parte de la tabla será incluida en el diseño. Sin embargo cuando haya objetos, la expresión “container/objectValues” será evaluada dos veces, lo cual es un poco ineficiente. Además, si usted quiere cambiar la expresión, tendrá que cambiarla en ambos lugares.
Para evitar estos problemas, puede definir una variable para que contenga la lista y luego usarla en ambos casos: tal:condition y tal:repeat. Cambie las primeras líneas para que se vean así:
<table border="1" width="100%"
tal:define="items container/objectValues"
tal:condition="items">
<tr>
<th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th>
</tr>
<tbody tal:repeat="item items">
La sentencia tal:define crea la variable items, y la puede usar en cualquier parte de la etiqueta de la tabla. Note también cómo puede tener dos atributos TAL en la misma etiqueta table. De hecho puede tener tantas como quiera, en este caso, son evaluadas en orden La primera asigna la variable items y la segunda usa items en una condición para ver si es falsa (en este caso, una secuencia vacía) o verdadera.
Ahora supongamos que en lugar de simplemente no mostrar la tabla cuando no hay elementos, usted desea mostrar un mensaje. Para hacer esto, introduzca lo siguiente encima de la tabla:
<h4 tal:condition="not:container/objectValues">There Are No Items</h4>
La variable items no la puede usar todavía, ya que no está definida. Si usted mueve la definición a la etiqueta h4, no la puede usar más en la etiqueta table, porque se convierte en una variable local de la etiqueta h4. Puede situar la definición en una etiqueta que encierre a ambas h4 y table, pero hay una solución más simple. Al colocar la palabra clave global delante del nombre de la variable, hace que la definición dure desde la etiqueta h4 hasta el fondo de la plantilla:
<h4 tal:define="global items container/objectValues"
tal:condition="not:items">There Are No Items</h4>
<table border="1" width="100%"
tal:condition="items">
El not: en la primera tal:condition es un tipo prefijo de expresión que puede ser ubicado delante de cualquier expresión. Si la expresión es verdadera, not: es falso y viceversa.
La mayoría, sino todos, de objetos listados por su plantilla tiene una propiedad icono, que contiene la ruta al icono para ese tipo de objeto. Con el fin de mostrar este icono en la columna meta-type, tendrá que insertar esta ruta dentro del atributo src de una etiqueta img, mediante la edición de la columna meta-type en ambas filas para que se vean así:
<td>
<img src="/misc_/OFSP/Folder_icon.gif"
tal:attributes="src item/icon">
<span tal:replace="item/meta_type">Meta-Type</span>
</td>
La sentencia tal:attributes remplaza el atributo src de la imagen con el valor de item/icon. El valor de src en la plantilla actúa como un marcador de posición, de modo que la imagen no está dañada, y sea del tamaño correcto.
Ya que el atributo tal:content hubiera remplazado los contenidos completos de la celda, incluyendo las imágenes con le texto meta-type, este tiene que ser eliminado. En su lugar, se inserta el meta-type en línea de la misma manera como la dirección URL en la parte superior de la página.
Basado en el Zope Book, (C) Zope Corporation
Hasta ahora, ha visto cómo las Plantillas de página se pueden utilizar para añadir comportamientos dinámicos a las páginas Web individuales. Otra característica de las Plantillas de página es la posibilidad de reutilizar elementos de apariencia a través de muchas páginas.
Por ejemplo, con las Plantillas de página, puede tener un sitio que tenga un aspecto estándar. Y no importa el “contenido” de una página, igual tendrá un encabezado estándar, barra lateral, pie de página, y/u otros elementos de página. Este es un requisito muy común para los sitios web, y así es exactamente como funciona Plone.
Puede reutilizar los elementos de presentación a través de las páginas con macros . Los Macros definen la sección de una pagina que puede ser reutilizada en otras páginas. Un macro puede ser una página completa, o sólo una parte de ella como el encabezado o pié de página. Después de que define uno o más macros en una Plantilla de página, puede usarlos en otras Plantillas de páginas.
Puede definir macros con atributos de etiqueta similares a las sentencias TAL. Atributos de etiquetas macro son también denominados sentencias Macro Expansion Tag Attribute Language (METAL) o en Español Lenguaje de Expansión Macro para Atributos de Plantillas. Aquí hay un ejemplo de definición macro:
<p metal:define-macro="copyright">
Copyright 2008, <em>Foo, Bar, and Associates</em> Inc.
</p>
Esta sentencia metal:define-macro define un macro llamado “copyright”. El macro consiste del elemento p (incluye todos los elementos contenidos que terminan con una etiqueta de cierre p).
Los macros definidos en una Plantilla de página son almacenados en el atributo macros de la plantilla. Puede usar los macros de otra Plantilla, refiriéndose a ellos a través del atributo macros de una Plantilla de página en la cual están definidos. Por ejemplo supongamos que el macro copyright está en una Plantilla de página llamada “master_page”. Aquí está como usar el macro copyright desde otra Plantilla de página:
<hr />
<b metal:use-macro="container/master_page/macros/copyright">
Macro goes here
</b>
En esta Plantilla de página el elemento b será completamente remplazado por el macro cuando Zope renderice la página.
<hr />
<p>
Copyright 2008, <em>Foo, Bar, and Associates</em> Inc.
</p>
Si usted cambia el macro (por ejemplo si cambia el titular de los derechos de autor), todas las Plantillas de página que usen este macro automáticamente reflejaran el cambio.
Note cómo el macro es identificado por una expresión de ruta utilizando la sentencia metal:use-macro. La sentencia metal:use-macro remplaza el elemento de sentencia con el macro nombrado.
Las sentencias metal:define-macro y metal:use-macro son bastante sencillas. No obstante hay algunas sutilezas en sus usos, que vale la pena mencionar.
El nombre de un macro debe ser único dentro de la Plantilla de página en la que se define. Puede definir más de un macro en una plantilla, pero todos necesitan nombres distintos.
También hay que señalar que a pesar del atributo define-macro, el macro sigue siendo una sección regular de la plantilla; así que cuando llama a la plantilla completa, la sección macro es renderizada con el diseño de la página igual que cualquier otra sección de la misma. Cuando usa el atributo define-macro simplemente está agregando una especie de “ancla” a esa sección, por lo que se puede llamarse desde otra parte, pero no va a cambiar nada respecto al comportamiento de la misma sección en la propia plantilla.
Normalmente usted hace referencia a un macro en una sentencia metal:use-macro con una expresión de ruta. Sin embargo, puede utilizar cualquier tipo de expresión que desee, siempre y cuando devuelva un macro. Por ejemplo:
<p metal:use-macro="python:context.getMacro()">
Replaced with a dynamically determined macro,
which is located by the getMacro script.
</p>
En este caso la expresión de ruta devuelve un macro definido dinámicamente por el script getMacro. El uso de expresiones Python para localizar macros le permite variar de forma dinámica cual macro su plantilla utiliza.
Puede usar la variable por defecto con la sentencia metal:use-macro:
<p metal:use-macro="default">
This content remains - no macro is used
</p>
El resultado es el mismo que al usar default con tal:content y tal:replace. El contenido “default” en la etiqueta no cambia cuando sea renderizado. Esto puede ser útil si usted necesita condicionalmente utilizar un macro o caer en el contenido por defecto si este no existe.
Si trata de utilizar la variable nothing con metal:use-macro obtendrá un error ya que nothing no es un macro. Si usted quiere utilizar nothing para que condicionalmente incluya un macro, debería entonces encerrar la sentencia metal:use-macro con una sentencia tal:condition.
Zope maneja macros primero al renderizar sus plantillas. Luego Zope evalúa las expresiones TAL. Por ejemplo, considere este macro:
<p metal:define-macro="title"
tal:content="template/title">
template's title
</p>
Cuando se utiliza este macro se insertará el título de la plantilla en la cual el macro es utilizado, y no el título de la plantilla en la que se define el macro. En otras palabras, cuando se utiliza un macro, es como copiar el texto de un macro dentro de la plantilla y luego renderizar su plantilla.
Las macros son mucho más útiles si se pueden anular partes de ellos al momento de utilizarlos. Puede hacer esto definiendo slots (ranuras) en el macro que puede llenar cuando use la plantilla. Por ejemplo, considere un macro de barra lateral:
<div metal:define-macro="sidebar">
Links
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/support">Support</a></li>
<li><a href="/contact">Contact Us</a></li>
</ul>
</div>
Este macro está bien, pero supongamos que le gustaría incluir información adicional en la barra lateral sobre algunas páginas. Una manera de lograr esto es con ranuras:
<div metal:define-macro="sidebar">
Links
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/support">Support</a></li>
<li><a href="/contact">Contact Us</a></li>
</ul>
<span metal:define-slot="additional_info"></span>
</div>
Cuando use este macro puede elegir ocupar la ranura de este modo:
<p metal:use-macro="container/master_page/macros/sidebar">
<b metal:fill-slot="additional_info">
Make sure to check out our <a href="/specials">specials</a>.
</b>
</p>
Cuando renderice esta plantilla la barra lateral incluirá información adicional que usted haya proporcionado en la ranura:
<div>
Links
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/support">Support</a></li>
<li><a href="/contact">Contact Us</a></li>
</ul>
<b>
Make sure to check out our <a href="/specials">specials</a>.
</b>
</div>
Note cómo el elemento span que define la ranura es remplazado con el elemento b para que llene la ranura.
Un uso común de la ranura es proporcionar presentación por defecto la cual puede personalizar. En el ejemplo de ranura de la última sección, la definición de ranura era simplemente un elemento span vacío. Sin embargo, usted puede proporcionar presentación por defecto en una definición de ranura. Por ejemplo, considere este macro revisado de barra lateral:
<div metal:define-macro="sidebar">
<div metal:define-slot="links">
Links
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/support">Support</a></li>
<li><a href="/contact">Contact Us</a></li>
</ul>
</div>
<span metal:define-slot="additional_info"></span>
</div>
Ahora la barra lateral es completamente personalizable. Puede llena los enlaces de la ranura para redefinir los enlaces de la barra lateral. Sin embargo, si decide no ocupar el puesto de enlaces obtendrá entonces los vínculos predeterminados que aparecen dentro de la definición de la ranura.
Usted puede incluso tomar esta técnica más a fondo mediante la definición de ranuras dentro de ranuras. Esto le permite sustituir presentación por defecto con un buen grado de precisión. Aquí hay un macro de barra lateral que define ranuras dentro de ranuras:
<div metal:define-macro="sidebar">
<div metal:define-slot="links">
Links
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/support">Support</a></li>
<li><a href="/contact">Contact Us</a></li>
<span metal:define-slot="additional_links"></span>
</ul>
</div>
<span metal:define-slot="additional_info"></span>
</div>
Si usted desea personalizar los enlaces de la barra lateral puede llenar las ranuras de enlaces para sustituir los enlaces completamente, o puede llenar la ranura additional_links para insertar algunos enlaces adicionales después de los enlaces predeterminados. Usted puede modificar ranuras tanto como quiera.
Usted puede usar ambas sentencias METAL y TAL en los mismos elementos. Por ejemplo:
<ul metal:define-macro="links"
tal:repeat="link context/getLinks">
<li>
<a href="link_url"
tal:attributes="href link/url"
tal:content="link/name">link name</a>
</li>
</ul>
En este caso, getLinks es un script (imaginario) que reúne una lista de objetos de enlace, posiblemente usando un consulta de Catálogo.
Ya que las sentencias METAL son evaluadas primero que las sentencias TAL, no hay conflictos. Este ejemplo es interesante también porque personaliza un macro sin usar ranuras. El macro llama el script getLinks para determinar los enlaces. De esta manera puede personalizar los enlaces de su sitio rédefiniendo el script getLinks sobre distintas locaciones dentro de su sitio.
No siempre es fácil descubrir la mejor manera de personalizar el aspecto de distintas partes de su sitio. En general, usted debe utilizar las ranuras para sustituir elementos de presentación, y se debe utilizar scripts para proporcionar contenido dinámico. En el caso del ejemplo de enlaces, es discutible si los enlaces son contenido o presentación. Probablemente los scripts proporcionan una solución más flexible, especialmente si su sitio incluye objetos de contenido.
En lugar de utilizar macros para partes de presentación compartida entre las páginas, puede utilizar macros para definir páginas completas. Las ranuras hacen esto posible. Aquí hay un macro que define la página completa:
<html metal:define-macro="page">
<head>
<title tal:content="context/title">The title</title>
</head>
<body>
<h1 metal:define-slot="headline"
tal:content="context/title">title</h1>
<p metal:define-slot="body">
This is the body.
</p>
<span metal:define-slot="footer">
<p>Copyright 2008 Fluffy Enterprises</p>
</span>
</body>
</html>
Este macro define una página con tres ranuras: headline (encabezado), body (cuerpo), y footer (pié de página). Note como la ranura headline incluye una sentencia TAL para determinar dinámicamente el contenido del encabezado.
Luego usted puede usar este macro en plantillas para diferentes tipos de contenidos, o distintas partes de su sitio. Aquí hay un ejemplo de cómo un elemento de noticia puede usar este macro:
<html metal:use-macro="container/master_page/macros/page">
<h1 metal:fill-slot="headline">
Press Release:
<span tal:replace="context/getHeadline">Headline</span>
</h1>
<p metal:fill-slot="body"
tal:content="context/getBody">
News item body goes here
</p>
</html>
Esta plantilla rédefine la ranura headline para que incluya las palabras “Press Release” (Notas de prensa) y ejecuta el método getHeadline en el objeto actual. También rédefine la ranura body para que ejecute el método getBody en el objeto actual.
Lo mejor de este enfoque es que ahora puede cambiar el macro de la página y la plantilla de notas de prensa será automáticamente actualizada. Por ejemplo usted puede poner el cuerpo de la página en una tabla y agregar una barra lateral a la izquierda y la plantilla de notas de prensa automáticamente usará estos elementos nuevos de presentación.
Basado en el Zope Book, (C) Zope Corporation
En esta parte vamos a ver algunas de las características más avanzadas del Lenguaje de Atributo de Plantilla, incluyendo un análisis más profundo a la Sintaxis de Expresiones TAL ().
Como ha podido ver en el ejemplo de la plantilla, usted puede situar más de una sentencia TAL en la misma etiqueta. Sin embargo, hay tres limitaciones que debería conocer:
Para superar estas limitaciones, se puede añadir otra etiqueta y dividir las sentencias entre las etiquetas. Si no hay ningún tipo obvio de etiqueta que encaje, use span o div.
Por ejemplo, si quiere definir una variable para cada repetición de un párrafo, usted no puede situar tal:define en la misma etiqueta que tal:repeat, ya que la definición pasará antes que todas las repeticiones. En cambio, podría escribir una de las siguientes:
<div tal:repeat="ph phrases">
<p tal:define="n repeat/ph/number">
Phrase number <span tal:replace="n">1</span> is
<b tal:content="ph">Phrase</b>.</p>
</div>
<p tal:repeat="ph phrases">
<span tal:define="n repeat/ph/number">
Phrase number <span tal:replace="n">1</span> is
<b tal:content="ph">Phrase</b>".</span>
</p>
Si usted necesita definir múltiples atributos en una etiqueta, no puede hacerlo mediante la colocación de múltiples sentencias tal:attributes en la etiqueta, y dividiéndolas de manera inservible por las etiquetas.
Ambas sentencias tal:attributes y tal:define pueden tener partes múltiples en una sola sentencia. Para separar partes se utiliza el punto y coma (;), así que cualquier expresión que contenga punto en coma en estas sentencias debe repetirse dos veces (;;). Aquí hay un ejemplo de configuración de ambos atributos src y alt de una imagen:
<img src="default.jpg"
tal:attributes="src item/icon; alt item/id">
Aquí hay una mezcla de definiciones de variables:
<span tal:define="global logo context/logo.gif;
ids context/objectIds">
Expresiones de cadenas le permiten fácilmente mezclar expresiones de ruta con texto. Todo el texto después del string: líder se toma y se busca para expresiones de ruta. Cada expresión de ruta de precederse por un símbolo de dolar ($). Si tiene más de una parte, o debe ser separado del texto que le sigue, debe estar rodeado por llaves ({}). Ya que el texto está dentro de un valor de atributo, sólo puede incluir una cita doble usando la sintaxis de entidad ". Debido a que los símbolos de dolar son usados para señalar expresiones de ruta, un símbolo de dolar literal debe repetirse dos veces ($$). Por ejemplo:
<span tal:replace="string:Just text."/>
<span tal:replace="string:(C) $year, by Me."/>
<span tal:replace="string:Three ${vegetable}s, please."/>
<span tal:replace="string:Your name is ${user/getUserName}!"/>
<span tal:replace="string:She answered "$answer"."/>
<span tal:replace="string:This product costs $price$$."/>
Una expresión de ruta ordinaria trata de renderizar el objeto que manda a llamar. Esto significa que si el objeto es una función, script, método, o algún otro tipo de elemento ejecutable, la expresión evaluará el resultado de llamar al objeto. Usualmente esto es lo que se quiere, pero no siempre es el caso. Por ejemplo, si usted quiere poner un documento DTML dentro de una variable para que así pueda referirse a sus propiedades, no puede usar entonces una expresión normal de ruta ya que renderizará el documento dentro de una cadena.
Si introduce un prefijo de expresión nocall: delante de una ruta, previene la renderización y simplemente le da el objeto. Por ejemplo:
<span tal:define="doc nocall:context/aDoc"
tal:content="string:${doc/id}: ${doc/title}">Id: Title</span>
Este tipo de expresión también es útil cuando quiere definir una variable que mantenga una función o una clase de un módulo, para su uso en una expresión Python.
Ya usted ha visto algunos ejemplos de variables integradas template, user, repeat, y request. Aquí está una lista más completa de las otras variables integradas y sus usos:
La ruta template/title se garantiza que existe cada vez que una plantilla es usada, sin embargo esta puede ser una cadena en blanco. Algunas rutas tal como request/form/x, puede que no existan durante algunas renderizaciones de la plantilla. Normalmente esto causa un error cuando la ruta es evaluada.
Cuando una ruta no existe, a menudo tiene una ruta de retorno o valor que le gustaría usar en su lugar. Por ejemplo si request/form/x no existe, quizá quiera usar en su lugar context/x. Puede hacer esto listando las rutas en orden de preferencia, separados por caracteres plecas (|):
<h4 tal:content="request/form/x | context/x">Header</h4>
Dos variables que son bastante útiles como la última ruta en un lista de alternativas son nothing y default. Use nothing para poner en blanco el objetivo si ninguna de las rutas es encontrada o default para dejar el texto de ejemplo en su lugar.
También puede probar la existencia de una ruta directamente con el prefijo de ruta exists: . Una ruta de expresión con el prefijo exists: delante de ella será verdadera si la ruta existe, y falsa si no existe. Estos dos ejemplos mostrarán un mensaje de error sólo si esta pasa la solicitud:
<h4 tal:define="err request/form/errmsg | nothing"
tal:condition="err" tal:content="err">Error!</h4>
<h4 tal:condition="exists:request/form/errmsg"
tal:content="request/form/errmsg">Error!</h4>
Usted puede incluir elementos de página que son visibles en la plantilla pero son lo están en texto generado mediante el uso de la variable integrada nothing, como esta:
<tr tal:replace="nothing">
<td>10213</td><td>Example Item</td><td>$15.34</td>
</tr>
Esto puede ser útil para rellenar las partes de la página que se ocupan más por la página generada que por la plantilla. Por ejemplo, una tabla que usualmente tiene diez filas sólo tendrá una en la plantilla, agregando nueve filas dummy, el resultado de la plantilla lucirá mas parecida al resultado final.
Normalmente las sentencias tal:replace y tal:content citan el texto que insertan, convirtiendo < a < por ejemplo. Si usted quiere insertar el texto no citado, necesita preceder la expresión con la palabra clave structure. Dada una variable copyright con un valor de cadena de “(C) 2008 By <b>Me</b>”, las siguientes dos líneas:
<span tal:replace="copyright">Copyright 2008</span>
<span tal:replace="structure copyright">Copyright 2008</span>
...generarán “(C) 2001 By <b>Me</b>” y “(C) 2001 By Me” respectivamente.
Esta característica es especialmente útil cuando se está insertando un fragmento de código HTML que es almacenado en una propiedad o generado por otro objeto Zope. Por ejemplo, es posible que tenga elementos de noticias que contienen simple código de marcado HTML tales como texto en negrita y cursiva cuando se renderizan, y desea conservarlos cuando los inserte dentro de una área de “Noticias más importantes” de la página. En este caso, podría escribir:
<p tal:repeat="article topnewsitems"
tal:content="structure article">A News Article</p>
Una expresión Python comienza con python:, seguida por una expresión escrita en el lenguaje Python. Python es un lenguaje de programación sencillo y expresivo. Si nunca se había encontrado con en él antes, debería leer una de las excelentes tutoriales o introducciones disponibles en el sitio oficial http://www.python.org.
Una expresión de Plantilla de página Python puede contener cualquier cosa que el lenguaje Python considere una expresión. Puede usar sentencias tales como if y while,y las restricciones de seguridad de Zope son aplicadas.
Un lugar donde las expresiones Python son prácticamente necesarias es en la sentencia tal:condition. Por lo general, se quiere comparar dos cadenas o números, y no hay otra manera de hacer eso. Puede usar operadores de comparación < (less than), > (greater than), == (equal to), y != (not equal to). También puede usar operadores booleanos and, not, y or. Por ejemplo:
<p tal:repeat="widget widgets">
<span tal:condition="python:widget.type =='gear'">
Gear #<span tal:replace="repeat/widget/number">1</span>:
<span tal:replace="widget/name">Name</span>
</span>
</p>
Algunas veces usted desea escoger distintos valores dentro de una sola sentencia sobre la base de una o más condiciones. Eso lo puede hacer con la función test, como esta
You <span tal:define="name user/getUserName"
tal:replace="python:test(name=='Anonymous
User', 'need to log in', default)">
are logged in as
<span tal:replace="name">Name</span>
</span>
<tr tal:define="oddrow repeat/item/odd"
tal:attributes="class python:test(oddrow,
'oddclass', 'evenclass')">
Usted puede usar otros tipos de expresiones dentro de una expresión Python. Cada tipo tiene una función correspondiente con el mismo nombre, incluyendo path(), string(), exists(), y nocall(). Esto le permite escribir expresiones tales como:
"python:path('context/%s/thing' % foldername)"
"python:path(string('context/$foldername/thing'))"
"python:path('request/form/x') or default"
La última línea del ejemplo tiene un significado ligeramente diferente que la expresión de ruta “request/form/x | default”, ya que usará el texto por defecto si “request/form/x” no existe o si este es falso.
Gran cantidad del poder de Zope involucra enlazar objetos especializados. Sus Plantillas de páginas pueden usar Scripts, SQL Methods, Catalogs, y objetos predeterminados de contenidos. Con el fin de utilizarlos, hay que saber cómo acceder a ellos.
Las propiedades de objetos son generalmente atributos, así que puede obtener el título de una plantilla con la expresión “template.title”. La mayoría de objetos Zope aceptan adquisición, lo que les permite obtener atributos de objetos “padres”. Esto significa que la expresión Python “context.Control_Panel” adquirirá el Objeto de Panel de control de la carpeta root. Los métodos de objetos son atributos, como en “context.objectIds” y “request.set”. Los objetos contenidos en una carpeta se pueden acceder como atributos de la carpeta, pero ya que suelen tener identificaciones que no son identificadores Python válidos, no puede utilizar la notación normal. Por ejemplo en lugar de escribir “context.penguin.gif” debe escribir “getattr(context, ‘penguin.gif’)”.
Algunos objetos tales como request, modules, y acceso de elementos de soporte para carpetas Zope. Algunos ejemplos de esto son:
request['URL'], modules['math'], and context['thing']
Cuando se utiliza el acceso de elemento en una carpeta, este no trata de adquirir el nombre, por lo que sólo tendrá éxito si en realidad hay un objeto con ese ID contenidos en la carpeta.
Las expresiones de ruta le permiten ignorar los detalles de cómo llegar de un objeto a otro. Zope trata el acceso a atributos, luego el acceso a elementos. Puede escribir “context/images/penguin.gif” en vez de “python:getattr(context.images, ‘penguin.gif’)”, y “request/form/x” en lugar de “python:request.form[‘x’]”.
El intercambio es que las expresiones de ruta no le permiten especificar esos detalles. Por ejemplo. si usted tiene una variable de formulario “get”, debe escribir “python:request.form[‘get’]”, ya que “request/form/get” evaluará al método “get” del diccionario del formulario.
Los objetos scripts a menudo son usados para encapsular lógicas de negocios y manipulación compleja de datos. En el momento que usted se encuentre escribiendo una gran cantidad de sentencias TAL con expresiones complicadas dentro de ellas, debería considerar si un script haría el trabajo mejor.
Cada script tiene una lista de parámetros que espera recibir cuando se le llama. Si esta lista está vacía, entonces puede usar el script usando una expresión de ruta. De otra forma, necesitará usar una expresión Python como esta:
"python:context.myscript(1, 2)"
"python:context.myscript('arg', foo=request.form['x'])"
Si desea devolver más de un solo bit de datos desde un script a una plantilla de página, es una buena idea devolverlo en un diccionario. De esta manera, se puede definir una variable para contener todos los datos, y el uso de expresiones de ruta para hacer referencia a cada bit. Por ejemplo suponga que tenemos un script getPerson el cual llama un diccionario como {'nombre':'Fred', 'edad':25}:
<span tal:define="person context/getPerson"
tal:replace="string:${person/name} is
${person/age}">Name is 30</span> years old.
DTML es otro lenguaje de plantillas disponible para Zope, en la actualidad mayormente remplazado por ZPT, pero sigue estando en uso. Puede leer más acerca de esto en the relevant chapter of the Zope Book.
A diferencia de Scripts, Métodos DTML no tienen ninguna lista explicita de parámetros. En cambio, esperan que sea pasado un cliente, un mapeo, y argumentos de palabras claves. Se utilizan para construir un espacio de nombres.
Cuando ZPublisher de Zope publica objetos DTML, pasa el contexto del objeto como el cliente, y el REQUEST como el mapeo. Cuando un objeto DTML llama a otro, pasa su propio espacio de nombres como el mapeo, y sin cliente.
Si usted utiliza una expresión de ruta para renderizar un objeto DTML, este pasará un espacio de nombres con request, context, y las variables de plantilla que ya están con él. Esto significa que el objeto DTML será capaz de utilizar los mismos nombres como si hubieran sido publicados en el mismo contexto que la plantilla, junto con los nombres de las variables definidas en la plantilla.
El lenguaje Python viene con un gran número de módulos, que proporcionan una amplia variedad de capacidades para los programas Python. Cada módulo es un conjunto de funciones, datos y las clases Python relacionadas con un solo propósito, tales como cálculos matemáticos o expresiones regulares.
Varios módulos, como “math” y “string”, están disponibles en las expresiones Python por defecto. Por ejemplo puede obtener el valor de pi desde módulo math escribiendo “python:math.pi”. Sin embargo para acceder desde una expresión de ruta, necesita usar la variables de modules. En este caso usaría “modules/math/pi”. Por favor consulte el libro Zope o a una guía de referencia DTML para obtener más información sobre estos módulos.
El módulo “string” está escondido en expresiones Python por la función de expresión “string”, así que tiene que entrar a través de la variable modules. Usted puede hacer esto directamente con una expresión que lo use, o definir una variable global para él, de esta manera:
tal:define="global mstring modules/string"
tal:replace="python:mstring.join(slist, ':')"
Los módulos se pueden agrupar en paquetes, que son simplemente una forma de organizar y nombrar los módulos relacionados. Por ejemplo, los scripts de Zope de base-Python son proporcionados por una colección de módulos en el sub-paquete “PythonScripts” del paquete de Zope “Products”. En particular el módulo “standard” dentro de este paquete proporciona un número de funciones para formato útiles que son estándares en la etiqueta DTML “Var”. El nombre completo de este módulo es “Products.PythonScripts.standard”, así que puede obtener acceso a él usando cualquiera de la siguientes sentencias:
tal:define="pps modules/Products.PythonScripts.standard"
tal:define="pps python:modules['Products.PythonScripts.standard']"
La mayoría de los módulos Python no se pueden acceder desde Plantillas de página, DTML, o scripts a menos que agregue a ellos las declaraciones de seguridad de Zope. Pero esta información está fuera del alcance de este documento; la puede revisar en Zope Security Guide (Guía de Seguridad de Zope).
Los atributos HTML booleanos checked*,* selected, nowrap, compact, ismap, declare, noshade, disabled, readonly, multiple, selected y noresize son tratados de manera diferente por tal:attributes. El valor es verdadero o falso (como es definido por tal:condition). El atributo se define para attr=”attr” en caso verdadero y omitido en el caso contrario. Si el valor es default, se considera entonces como verdadero si el atributo ya existe, y falso si no existe. Por ejemplo cada una de las siguientes líneas:
<input type="checkbox" checked tal:attributes="checked default">
<input type="checkbox" tal:attributes="checked string:yes">
<input type="checkbox" tal:attributes="checked python:42">
se renderizará como:
<input type="checkbox" checked="checked">
mientras que cada uno de estos:
<input type="checkbox" tal:attributes="checked default">
<input type="checkbox" tal:attributes="checked string:">
<input type="checkbox" tal:attributes="checked nothing">
se renderizará como:
<input type="checkbox">
Este articulo contiene información y ejemplos del Zope Book, (C) Zope Developers Community.
Plone define algunas variables globales útiles para usarlas en sus plantillas
Cuando este escribiendo plantillas para Plone, se dará cuenta de un conjunto de variables que usa más seguido, como la URL del portal o el miembro actualmente autenticado.
Para su conveniencia, Plone define algunas variables globales de plantillas que son traídas a main_template vía global_defines. Algunas de los más útiles son:
Para ver la lista completa de estas variables revise la docstring para la función globalize() en la interfaz Products.CMFPlone.browser.interfaces.IPlone.
En este tutorial se describen los pasos para producir una vista totalmente personalizada de objetos de Arquetipos. Esto es aplicable para afinar pequeños detalles de comportamiento por defecto AT así como la destrucción y reconstrucción de la vista a partir de cero. (Aportado por Floyd May)
Objetivos, prerrequisitos y herramientas
Si usted piensa que la manera en que Archetypes (Arquetipos) automáticamente genera HTML para ver su objeto no sea lo suficientemente bonita, pues ¡ha venido al lugar correcto! Voy a enseñarle cómo adornar esas monótonas y aburridas vistas y hacer que ¡brillen!
Esta página describe cómo Arquetipos usa diferentes plantillas para generar HTML, y como se puede aplicar la personalización a plantillas de base-AT.
Arquetipo posee un sistema bastante inteligente para generar páginas HTML para objetos de base-AT. El mismo conjunto de plantillas genera todas las áreas de contenido para todos los objetos de base-AT. Esto le compra el siguiente beneficio, provechoso para la consistencia del sitio:
Sin embargo también tienen el siguiente inconveniente:
Diferentes tipos de contenido necesitan mostrarse de diferente manera. Averigüemos cómo Arquetipos hace las cosas, para que podamos descubrir cómo hacer que los tipos de contenido ¡brillen!
La plantilla base_view (se encuentra en el skin de arquetipos) se encarga de seleccionar el macro apropiado desde la plantillas apropiadas, y usa esos macros para mostrar el contenido. Si observa este parte del código de ‘base_view’:
<tal:block define="portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
view_template
python:'%s_view' % portal_type;
view_macros
python:path('here/%s/macros|nothing' %
view_template);
macro
view_macros/css | nothing"
condition="macro">
Puede ver que define la variable view_template como el Nombre de portal cambiado a minúsculas y subguiones (_) en vez de espacios, seguido de _view. Por ejemplo la plantilla MyType’s view se llamaría mytype_view.
Ahora antes de continuar le debo advertir que no edite base_view. En serio, no lo haga. [1]
En serio NO personalice base_view. Si cree que necesita personalizar primero base_view, pues...no lo haga. Siga leyendo este tutorial. Si después de leer esta tutorial, esta seguro que necesita personalizar base_view, ¡NO! lo haga. Escriba un ejemplo claro y conciso indicando por qué después de leer esta tutorial, cree que debería personalizar base_view, y envíela la lista de correos de archetypes-users. Si usted necesita realmente personalizar base_view, pues habrá encontrado un defecto en Arquetipos, y las personas en la lista le confirmarón que ese es su caso particular. Así que repita después de mí: “No personalizar base_view.” ¡Bien!
Ahora, hay que tener en cuenta seis macros importantes. Estos seis macros le dan el poder para insertar código de plantilla que es personalizado por su clase. Estos macros son:
js Un macro para insertar javascript dentro de la etiqueta <head> de la página HTML generada. css Un macro para insertar CSS y código de estilo dentro de la etiqueta <head> de la página header El macro que define la parte superior del área de contenido. Por defecto este macro tiene un etiqueta <h1> que contiene el título, enlaces para imprimir, enviar correo, etc. en la parte derecha. body Este macro define el área de “body” (cuerpo) del contenido Aquí es donde se muestran los campos y sus valores. folderlisting Este macro muestra una lista del contenido hijo para un objeto. No lo confunda con folder_contents, esto es lo que la pestaña vista muestra para objetos folderish. Objetos folderish usan ambos macros body y folderlisting. footer Aquí es donde AT pone la línea de fondo.
Como puede ver el macro header genera dentro del contorno marcado en rojo como “header” (encabezado), el macro body genera el contenido justo abajo de este, y el macro folderlisting genera la lista de objetos dentro del objeto folderish.
La plantilla base_view extrae automáticamente el macro apropiado de vista por defecto (mytype_view, de nuestro ejemplo ad-hoc anterior), o de la próxima plantilla que exploraremos: base.
La plantilla base contiene cuatro de los seis macros buscados por base_view:
La única razón por la que he mencionado base es para que sepa de donde proviene el comportamiento AT por defecto. Esto es importante si usted sólo desea cambiar un poco de la vista de un tipo. Regularmente es útil copiar el macro desde base a su plantilla de vista por defecto o predeterminada, y luego empezar a ajustar y personalizar.
Un Widget es lo que usa Arquetipos para mostrar campos. Estos poseen dos partes:
Hay todo tipo de widgets en el mercado que hacen todo tipo de cosas. El Archetypes Quick Reference Manual (Manual rápido de referencia para Arquetipos) cubre los detalles para distintos widgets en Arquetipos.
[1] A menos que está apurado o nervioso.
Esta página le muestra cómo personalizar widgets, y da algunos ejemplos de qué tipo de ingeniosos trucos se pueden hacer con la personalización de widgets.
Como ya hemos dicho, los widgets son lo que Arquetipos utiliza para mostrar los campos individuales. Las plantillas integradas en Arquetipos, base_view, base, y widgets/field usan cada campo y widget de campo asociado (especificado en el esquema) para determinar cual plantilla de widget usar. No obstante, puede sustituir un plantilla de widget, como mostraremos más abajo. Además, puede crear una clase completamente nueva de widget, que tendrá los datos y las operaciones específicas para la presentación de tipos datos por defecto. Lea la siguiente sección para determinar que tanto hackeo de widget tiene que hacer.
Si no puede encontrar un widget en Archetypes (Arquetipos) o en productos de disponibilidad fácil hechos por terceros que hagan lo que usted necesite, use el siguiente grupo de preguntas para determinar si puede simplemente personalizar una plantilla versus crear una nueva clase de widget. Si responde “no” a las siguientes preguntas, una plantilla personalizada es todo lo que necesita:
Si usted contestá “sí” a la mayoría de las preguntas, entonces puede que tenga que crear una clase widget. Si le parece que las preguntas no están claras, eche un vistazo a RichDocument tutorial . Si usted tiene un caso lo suficientemente específico (como RichDocument) en el que necesita clases de widget personalizadas, probablemente pueda hacerlo por el simple hecho de saber que los necesita. [1]
La creación de plantillas widget personalizadas no es difícil, así que no tenga miedo. Asumo que si está leyendo esta sección ya debe haber determinado que usted no necesita una clase de widget personalizada, y simplemente necesita retocar un poco cómo se hacen las cosas por defecto.
En primer lugar, usted debe entender que control tiene al personalizar una plantilla widget en sí misma. Usted está controlando la presentación de los datos del widget, pero no su label (rótulo). Para un StringField llamado myfield, la presentación por defecto será algo como:
myfield: some value (algún valor)
Lo único que podemos controlar es la presentación de lo que viene después de “myfield:”, que simplemente son los datos contenidos dentro del campo mismo (hablaremos de cómo personalizar los rótulos posteriormente) Sin embargo, si personalizamos la plantilla, ¡podemos insertar todo tipo de ingenioso HTML allá dentro! Así que veamos la plantilla StringWidget’, ‘widget/string’:
Es bastante sencilla Como puede ver, hay tres macros importantes en una plantilla widget:
No se preocupe por los macros edit y search; recuerde que estamos personalizando view (vista). Empecemos por crear una nueva plantilla llamada my_string_widget [2]. Comience de esta manera:
Observe cómo se utiliza la misma llamada de “pase-a través” macro en el macro edit que la plantilla string originalmente utiliza en el macro de search. Es importante recordar el siguiente concepto: las plantillas widget necesitan tener definidos los tres macros: view, edit, y search. También note cómo no existe un código de visualización para el rótulo, como es de costumbre en otras partes. Si se está preguntando de dónde viene la variable accessor, pues es parte del código de visualización del widget. La clase widget define las siguiente variables locales que son accesibles dentro de las plantillas widget:
Ahora vamos a modificar la manera en que StringField se muestra. Para brevedad, solo mostrará el macro view:
Luego deberíamos decirle a nuestro esquema de tipo que apunte a la nueva plantilla
StringField('myfield',
widget=StringWidget(
label='Myfield',
label_msgid='ATViewTutorial_label_myfield',
description_msgid='ATViewTutorial_help_myfield',
i18n_domain='ATViewTutorial',
macro='my_string_widget',
)
),
Asegúrese de reiniciar Zope y reinstalar usando portal_quickinstaller. Ahora cuando renderizamos StringField, se verá como este:
Así es amigos, es así de sencillo.
[1] Una vez más, esto probablemente sólo se aplica a cierto nerviosismo.
[2] Note que aquí estoy rompiendo la convención AT. Usted no tiene que hacer eso, pero yo encuentro más conveniente y inteligible añadir _widget a los nombres de mi plantillas widget.
Esta página describe cómo se puede controlar cada parte del diseño HTML en el área de contenido mediante la creación de una plantilla de vista personalizada.
Bueno, usted ya ha hackeado un poco las plantillas widget, y están disfrutando de la gloria de su poder recién descubierto, sin embargo, todavía usted no está satisfecho. ¡Quiere controlarlo todo! Bueno ¡yo tengo la información que usted necesita!
Arquetipos automáticamente reconoce las plantillas con nombre específicos, y usa el código dentro de esas plantillas para mostrar su objeto base-AT. Toda la magia ocurre dentro de la plantilla base_view. Para crear una plantilla de vista personalizada, convierta el nombre su tipo a minúscula (el myObject.portal_type). Ahora remplace los espacios con subguiones ( _ ). Y finalmente agregue _view al final del nombre, y ya casi tiene una plantilla de vista personalizada.
nombre que está listado en portal_types, o lo que se arroja desde Revise más abajo para ejemplos de nombres de tipos a sus respectivas plantillas de vista.
Nombre de tipo
Nombre de la plantilla de Vista
My Type
my_type_view
SomeTypeV2
sometypev2_view
Ahora para remediar la parte “casi” de la oración anterior, defina uno o más de los siguientes macros en su plantilla:
¡Eureka! Ya tiene una plantilla de vista personalizada. Para ver cómo funciona esto, cree una simple plantilla (por supuesto nombrada apropiadamente) que contenga el siguiente código:
:: Foo
Foo
Foo
Foo
Y como magia debería ver renderizado en área de contenido:
Así que ahora quiere sus datos devuelta. Usted dijo que quería total control, y ahora no quiere total control. Pero el punto de esta tutorial no es el control, es el brillo. Así que exploremos como mezclar y combinar las plantillas existentes AT con sus códigos personalizados para hacer una plantilla brillante que presente lo que usted quiera.
En primer lugar, mantenga presente la plantilla “Foo” anterior. Es bastante útil cuando no está seguro de cual de los cuatro macros está generando una porción del área de contenido. Simplemente comente uno o más de los macros, y verá que macro genera cual porción.
Ahora ?recuerda cuando hice referencia sobre el uso de la plantilla base como un punto de partida para la creación de plantillas personalizada sí Bueno, eso es lo que haremos. Empecemos por personalizar el pié de página. El macro footer en la siguiente plantilla es copiado directamente desde “base”:
Get the byline - contains details about author and modification date.
Ahora agreguemos algo debajo de la byline (línea de fondo), alguna información importante que se aplique a cada instancia de su tipo personalizado:
Get the byline - contains details about author and modification date.
Important information that applies to every instance of my custom
type.
Note que todo lo que tuvimos que hacer fue copiar el macro desde base , y añadir la etiqueta <p> con algún texto contenido en él. Note por ejemplo, que podríamos haber usado tal:content="here/getCustomFooterData" en la etiqueta </p> <p> si hubiéramos definido un método getCustomFooterData() en nuestra clase.
Apliquemos este concepto al macro body, y juegue un poco con los campos que se muestran. Primero empecemos por copiar el body (cuerpo) desde base en nuestra plantilla.
Ahora vamos a cambiar algunas cosas añadiendo un poco de código en la macro. Primero note que tal:repeat está repitiendo sobre todos los campos que no son metadatos. Por lo tanto, si quiere hacer algo para cada campo, colóquelo dentro de este macro. Usted podría (posiblemente) reorganizar el macro para que el bucle tal:repeat está dentro de otro bloque de contención, y ponga el código TAL antes y después de la presentación de los campos, o haga uso de las variables para repetir first y last para lograr la misma cosa. hagamos dos cosas para personalizar nuestro macro body:
Estos cambios, como estoy seguro que usted ha descubierto, no van a hacer mucha diferencia (en el caso de alguna) en el aspecto de la página renderizada sin escribir algún código CSS. Ahora introducimos el macro css:
<link href="#" type="text/css" rel="stylesheet" />
<div class="my-custom-at-body">
<div class="my-custom-at-field"> </div>
</div>
Podemos definir una stylesheet CSS llamada my_custom_css.css que contenga nuestro código CSS
.my-custom-at-body {
border: thin dashed;
background-color: #cccccc;
padding-top: 1em;
}
.my-custom-at-field {
background-color: #ffffff;
}
Arquetipos inserta el macro css dentro de la etiqueta de la página renderizada, creando nuestro código CSS personalizado, archivos enlazados, e incluye disponibles en la página. Nuestro resultado final será algo como esto:
Si hemos creado plantillas widget personalizadas, estas también serán aplicadas a las páginas renderizadas.
Todavía hay un elemento de control que nos falta: aún no se puede sustituir la presencia de un rótulo de campo. Al personalizar la visualización del rótulo, podemos insertar imágenes, enlaces, etc. dentro de la página en lugar de el rótulo por defecto.
El macro incluido en nuestra plantilla de vista personalizada a continuación hará la magia por nosotros:
<link href="#" type="text/css" rel="stylesheet" />
<div class="my-custom-at-body">
<div class="my-custom-at-field"> </div>
</div>
<label>Now presenting... Field1!</label>
Note que solo he sustituido el rótulo por defecto para los campos llamados “myfield”. El macro label (rótulo) en widgets/field es donde el comportamiento predeterminado se puede encontrar. El resultado final luce como este:
No olvide tampoco que tiene el poder de omitir head (encabezado), body (cuerpo), folderlisting (listado de carpetas), y footer (pié de página) simplemente escribiendo en macros sin-acción dentro de su plantilla de vista. Además, se puede llegar a su objeto y recuperar los valores de campo sin necesidad de utilizar el marco de widget.
Algunas notas finales sobre la personalización de las plantillas de vista en Arquetipos
Ahora ya debería saber toda la información siguiente:
Quiero presentar algunos detalles de cómo aplicar todas estas herramientas. un tipo sabio en algún momento dijo algo como, “Para el hombre cuya herramienta es un martillo, cada problema entonces tiende a lucir como un clavo”. Su éxito con Arquetipos realmente depende de la selección de la herramienta adecuada para el problema especifico. Por lo tanto, utilice el siguiente esquema del diseño básico de página AT como guía para determinar lo que debe ser personalizado:
Así que basado en cuales partes de este diseño estándar que necesita para personalizar, utilice el macro adecuado. Mantenga la infame plantilla “Foo” presente en caso de que necesite depurar Vea la siguiente página para una referencia sobre personalización de plantillas de vista en Arquetipos.
Una referencia para personalizar plantillas de vista en Arquetipos
Las plantillas son nombradas de acuerdo con la clase portal_type. Para crear el nombre de una plantilla, siga estos pasos:
Arquetipos localizará automáticamente las plantillas con nombres creados de acuerdo a los pasos anteriores, y hará uso de las macros definidos dentro de la plantilla. Plantillas de vista puede definir uno o más de las siguientes macros:
Para cualquiera de estos macros que no este definido en la plantilla de vista personalizada. Arquetipos usará el comportamiento por defecto en este lugar, tomado de base o widgets/field.
Use las plantillas widget personalizadas nombrándolas en el esquema; inserte un parámetro macro dentro del constructor widget en el esquema, y defina los valores para el nombre de la plantilla. Por ejemplo macro="my_widget_template". Las plantillas widget tienen que tener los siguientes tres macros:
Plantillas widget tienen las siguientes variables locales disponibles dentro de las expresiones TALES:
accessor El método accessor para el estado actual. El código <p tal:content="accessor" /> causará que el valor del campo se escriba dentro de la etiqueta <p>. fieldName El nombre del campo. widget El objeto de widget para el campo. mode Siempre será view para ver las plantillas, pero también puede ser útil para revisar errores.
Explica una forma de personalizar la vista o editar plantillas sin tener que cambiar la acción de un objeto.
Usualmente me gusta modificar lo menos posible para que más de las plantillas de mi página sean tal como las plantillas por defecto de Plone. Descubrí que esto me ayuda cuando me mudo a nuevas versiones y también hace que la creación del uso para estilos CSS sea más fácil.
Otro caso de uso es que si quiero generar un formulario utilizando el esquema pero lo necesito para hacer diferente las cosas en función de que botón se presiona, se puede lograr esto con la colocación de botones nombrados en el formulario en combinación con el uso de portal_formcontroller para sustituir lo que pasa en un envío. Ejemplo: para importar datos desde CSV en un esquema independiente tengo un botón form.button.Import y en este esquema sólo muestro este botón y el botón de cancelar, (en vez de guardar, siguiente, anterior, etc.) y luego personalizo la acción (y validación) portal_formcontroller para que content_edit (el script que guarda) vaya al script que hace la importación antes del volver a la acción de vista.
Ambas plantillas tienen varias macros que se consiguen a través de otras plantillas de páginas. Que están configuradas de tal manera que buscarán una plantilla llamada con el tipo de contenido para estos macros y luego predeterminar a las macros de arquetipos genéricos. Es decir, digamos que tiene un tipo de contenido llamado “Newsletter”, base_view busca por una plantilla llamada “newsletter_view”, si la encuentra y esta contiene los macros correctos usará esos en lugar de los predeterminados “view_macros” (Encontrados en la carpeta de skin “portal_skins/archetypes”).
A continuación se muestra un ejemplo del esqueleto de una plantilla de vista personalizada que muestra las diferentes cosas que se pueden personalizar. Ver base.pt
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en"
metal:use-macro="here/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:main fill-slot="main">
<!-- header, H1 with title in it -->
<metal:header define-macro="header">
</metal:header>
<!-- body macro where all the fields are -->
<metal:body define-macro="body">
</metal:body>
<!-- folderlisting that shows sub-objects if there are any -->
<metal:folderlisting define-macro="folderlisting">
</metal:folderlisting>
<!-- footer, by line created date etc. -->
<metal:footer define-macro="footer">
</metal:footer>
</metal:main>
</body>
</html>
Abajo hay un esqueleto de una plantilla de edición personalizada:
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en" lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone">
<metal:head define-macro="topslot">
</metal:head>
<metal:head define-macro="javascript_head">
</metal:head>
<body>
<!-- header, h1 of Edit <Type>, schemata links and webdav lock message -->
<metal:header define-macro="header">
</metal:header>
<!-- typedesription, typeDescription from the content type -->
<metal:typedescription define-macro="typedescription">
</metal:typedescription>
<!-- body, editform , fields, buttons, the default macro
contains a number of slots which usually
provide enough
ways to customise so often I use that macro
and just
fill the slots
-->
<metal:body define-macro="body">
<metal:default_body use-macro="here/edit_macros/macros/body">
<!-- inside the fieldset but above all the fields -->
<metal:block fill-slot="extra_top">
</metal:block>
<!-- listing of the fields, usually I won't customise this
<metal:block fill-slot="widgets">
</metal:block>
-->
<!-- below the fields above the
formControls (hidden fields for refernce stuff is above
buttons) -->
<metal:block fill-slot="extra_bottom">
</metal:block>
<!-- within the formControls these are
the default previous, next, save, cancel buttons -->
<metal:block fill-slot="buttons">
</metal:block>
<!-- within the formControls a slot for
extra buttons -->
<metal:block fill-slot="extra_buttons">
</metal:block>
</metal:default_body>
</metal:body>
<!-- footer, by line created date etc. -->
<metal:footer define-macro="footer">
</metal:footer>
</body>
</html>
Vea las plantillas dentro de Products.Archetypes:skins/archetypes para ejemplos sobre cómo hace Arquetipos para trabajar por defecto, obtenga las listas de campos, trabaje la traducción, maneje el procesamiento de formularios y más. Usándolas como base y personalización de sólo los detalles necesarios pueden hacer el trabajo mucho más fácil que empezar de cero.
Digamos que su tipo de contenido es “Newsletter“
En que lugar está almacenada el skin en Plone y en su propio producto de tema.
Puede personalizar todas las plantillas de página, skins y CSS muy fácilmente a través de la web.
Localice el elemento que desee cambiar, haga clic en el botón de personalizar y una copia será movida a la capa de personalización.
También puede agregar nuevas plantillas de páginas, scripts de Python y archivos (para CSS y JavaScript) a la capa de personalización mediante el uso de lista desplegable en la ZMI. En la mayoría de los casos, sin embargo, le resultará más fácil encontrar una plantilla en la cual desea basar la nueva plantilla, personalizarla y luego cambiarle el nombre a través de la ZMI.
No se olvide que si está cazando algo, en pestaña de Buscar en la ZMI puede ser muy útil.
Todas las plantillas de página, hojas de estilo, scripts y JavaScript para el skin por defecto de Plone se pueden encontrar en el producto CMFPlone:
Hojas de estilo
Usted puede hacer mucho con sólo reemplazar los estilos existentes de Plone. Hay stylesheet (hojas de estilo) disponibles sólo para este propósito.
Usted encontrará una stylesheet vacía llamada ploneCustom.css en
Este stylesheet está siempre cargado de último en una página, y por lo tanto puede utilizarse para sustituir cualquier otro estilo. Hay un excelente y completa tutorial sobre esto aquí:
verá que ploneCustom.css tiene una extensión .dtml, y la CSS que está en el interior está empaquetada
/* <dtml-with base_properties> */
.......
/* </dtml-with> */
DTML es otro lenguaje de plantillas de Zope, que en este caso se ha implementado de manera que ciertas variables puedan ser recogidas a partir de una hoja de propiedades (base_properties.props), por ejemplo:
#portal-column-one {
vertical-align: top;
width: <dtml-var columnOneWidth missing="16em">;
border-collapse: collapse;
padding: 0;
}
Nosotros no recomendamos el uso de esta técnica, ya que es probable que desaparezca, pero es bueno saber que está allá. Algunas veces puede quedar atrapado si está personalizando ploneCustom.css y accidentalmente elimina la parte superior o inferior de la sentencia “dtml-with” o se le olvida agregar la extensión .dtml.
Familiarizándose con las hojas de estilo de Plone
instrucciones para encontrar y modificar base_properties de Plone y CSS.
Esta tutorial describe el uso de CSS (Cascading Style Sheets - Hojas de Estilo en Cascada) en Plone 3.x y está pretendido para personalizadores de sitio que están familiarizados con CSS y poseen privilegios administrativos en un sitio Plone. Este enfoque está estrictamente hecho para crear modificaciones a-través-de-la-Web a stylesheets (hojas de estilo).
Ningún conocimiento previo de Python, Plone o Zope es requerido y los ejemplos guiarán a aquellos nuevos en Plone a través de cada paso requerido para hacer modificaciones CSS en Plone. Si usted ha montado un sitio Plone pero igual es nuevo en Plone, esta tutorial es para usted. Si es un diseñador Web que necesita trabajar como parte de un equipo de Plone, esta tutorial le puede ayudar a clarificar como la CSS es usada en Plone.
Por mucho, la herramienta introspector CSS más popular de sitios web es Firebug de Mozilla. No importa el nivel de su experiencia, Firebug es la última herramienta de depuración CSS y todos los personalizadores deberían utilizarla.
La idea básica es que usted puede recorrer el HTML que enmarca sus páginas de Plone, y ver la CSS que es aplicada al HTML. Usted puede incluso cambiar la configuración de CSS en el momento para experimentar con el diseño de su sitio. Para obtener ayuda sobre el uso de Firebug, haga clic aquí .
El uso extenso de CSS en Plone le da a los personalizadores una gran cantidad de control sobre la apariencia de un sitio Plone. La manera más rápida de obtener una idea de esto es mirar en un sitio Plone con los estilos deshabilitados en su explorador. En Firefox puede deshabilitar los estilos en “Ver>Estilo de la página>sin estilo”, (pruebe esto ahora). Claramente CSS es bastante usada, y la hace bastante provechosa para la separación de forma y contenido.
Diseño personalizado de un sitio Plone se puede realizar mediante una de las siguientes maneras:
Esta tutorial describirá las técnicas 1 y 2.
Note que las personalizaciones serias de la interfaz de Plone se hacen mejor creando productos personalizados. Estos le permiten encapsular todos los cambios de estilos y plantillas en un solo sitio, guardarlos y re-aplicarlos en otro sitio. Las instrucciones que se explican aquí son para personalizaciones “rápidas y robustas” en un sitio individual.
Antes de comenzar cualquier personalización CSS debería activar el modo debug-/development. Esto le garantizará que el almacenamiento en caché y la compresión de CSS está desactivada.
Esta es la manera en que se activa el modo depuración/desarrollo:
Cuando haya finalizado con las modificaciones de CSS debería desactivar el modo depuración/desarrollo, ya que este afecta el rendimiento de su sitio Plone.
Plone proporciona un grupo de base_properties que controlan ciertas cosas del color, fuente, logotipo y márgenes por defecto de Plone. Estas propiedades le permiten modificar la apariencia básica de un sitio sin trabajar directamente con los archivos CSS de Plone y proporciona la manera más simple de hacer personalizaciones básicas. Los nombres de propiedades individuales son razonablemente auto-explicativos (linkColor, borderStyle, etc.) y aceptar valores estándar de estilo CSS.
Así es como modifica base_properties:
La sección 3 de esta tutorial proporciona una descripción más detallada de cada una de las propiedades de base.
El siguiente paso más allá de las modificaciones de base_property es la substitución de la CSS de Plone con su propia CSS personalizada. Plone proporciona la stylesheet ploneCustom.css para las personalizaciones de sitio. La parte difícil para las personas nuevas en Plone es averiguar los selectores CSS que son usados dentro de Plone.
Para mucha gente, el Firebug o las extensiones de Firefox para desarrollo Web proporcionan la manera más fácil de inspeccionar los estilos asociados con los elementos HTML en una página web. Cualquiera de estas proporciona una forma fácil de acceso a los selectores CSS e información de estilo requerida para la creación de stylesheets personalizadas.
Note que los archivos .css en Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles son realmente plantillas dtml, lo que significa que pueden utilizar base_properties para hacer cambios globales vía variables. Esto quiere decir que pueden contener referencias a base_properties junto con CSS estándar, como en el siguiente ejemplo de public.css:
h1, h2 {
border-bottom: **&dtml-borderWidth;** **&dtml-borderStyle;**
**&dtml-globalBorderColor;**;
font-weight: normal;
}d
Aquí está cómo agregar personalizaciones CSS a su sitio Plone:
Las secciones 4 y 5 de este tutorial describen las stylesheets (hojas de estilo) de Plone y los selectores CSS asociados con los distintos elementos de la interfaz de Plone.
Cuando al principio comienza a jugar con base_properties y stylesheets usted querrá la libertad de hacer muchos cambios, pero sabiendo que igual puede regresar fácilmente a las configuraciones por defecto. Plone hace que esto sea fácil, siempre manteniendo las versiones de base_properties y stylesheets personalizadas en una carpeta separada. Cuando Plone reúne las stylesheets de CSS, este busca primero por versiones personalizadas y usa estas cuando las encuentra. Por otra parte si no las encuentra utiliza entonces las versiones por defecto. Para restablecer las configuraciones por defecto sólo necesita eliminar las versiones personalizadas.
Esta es la manera como restablece los estilos por defecto en su sitio Plone.
Ejemplos de personalización de Plone 3.0.x a través de base_properties y CSS.
Los siguientes ejemplos son proporcionados para darle un impulso en hacer cambios a su sitio. No se pretende que sean ejemplos completos. En cada caso tomaremos un sitio Web existente para usarlo como nuestro objetivo y hacer algunos cambios que imiten el estilo del objetivo. Terminar el estilo lo dejaremos como ejercicio para el estudiante.
Una de las maneras más fáciles de ver el control de base_properties es crear un estilo “oscuro” para su sitio. Como ejemplo de donde es apropiado este estilo usaremos Austin Neon como nuestro sitio. Como siempre, la extensión Firebug para Firefox es invaluable para inspeccionar el estilo de nuestro objetivo. Si usted todavía no la ha hecho, por favor instale y entre en confianza con Firebug antes de tratar de descubrir cómo el objetivo es estilizado.
El primer paso será modificar base_properties de nuestro sitio Plone como se describe en la sección 1. La siguiente captura muestra la base_properties que se acerca a representar los colores que se encuentran en nuestro objetivo. Vaya y realice estos cambios a su base_properties ahora.
TODO (marcador de código)
¿alguien desea hacer alguna contribución?
Descripción de todas las base_properties en Plone 3.0.x
La siguiente lista de base_properties son usadas para dar estilizar a través de Plone. Estas pueden editarse mediante la ZMI en Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles ‣ base_properties
Descripción de los stylesheets CSS por defecto en Plone 3.0.x.
Las stylesheets por defecto están descritas más abajo junto con las listas de los selectores CSS definidos en cada una. Las stylesheets son presentadas en el mismo orden en que están definidas en Interfaz de Administración de Zope ‣ portal_css para que el estilo definido en las stylesheets de más abajo sustituyan el estilo definido en las de más arriba.
Estilos para estados de flujo de trabajo de usuarios que hayan iniciado sesión.
.state-private { ... }
.state-visible { ... }
.state-published { ... }
.state-pending { ... }
.state-expired { ... }
.syndicated { ... }
Estilos de izquierda a derecha para el idioma árabe y hebreo
Estilos para elementos base (etiquetas HTML)
body { ... }
table { ... }
a { ... }
img { ... }
p { ... }
p img { ... }
hr { ... }
h1, h2, h3, h4, h5, h6 { ... }
h1 a{ ... }
h1 { ... }
h2 { ... }
h3 { ... }
h4 { ... }
h5 { ... }
h6 { ... }
ul { ... }
ol { ... }
li { ... }
dt { ... }
dd { ... }
abbr, acronym, .explain { ... }
abbr .explain { ... }
q { ... }
blockquote { ... }
code, tt { ... }
pre { ... }
ins { ... }
del { ... }
Gran cantidad de elementos destinados al público.
/* Accessibility elements, applied by JS */
body.largeText { ... }
body.smallText { ... }
/* Padding for the columns */
#portal-column-one .visualPadding { ... }
#portal-column-two .visualPadding { ... }
/* Content area */
h1, h2 { ... }
body.kssActive h2.inlineEditable:hover, body.kssActive
h1.inlineEditable:hover { ... }
h3, h4, h5, h6 { ... }
.documentFirstHeading { ... }
.documentContent { ... }
.documentContent ul { ... }
.documentContent ol { ... }
/* Links with differently colored link underlines - only for content
*/
.documentContent p a { ... }
.documentContent p a:visited { ... }
.documentContent p a:active { ... }
#content a:target { ... }
.documentContent li a { ... }
.documentContent li a:visited { ... }
.documentContent li a:active { ... }
.documentContent dd a { ... }
.documentContent dd a:visited { ... }
.documentContent dd a:active { ... }
/* End links */
#visual-portal-wrapper { ... }
/* Logo properties */
#portal-logo img { ... }
/* The skin switcher at the top, only shows up if you have multiple
skins available */
#portal-skinswitcher { ... }
#portal-skinswitcher a { ... }
#portal-top { ... }
/* Site-wide action menu - font size, contact, index, sitemap etc */
#portal-siteactions { ... }
#portal-siteactions li { ... }
#portal-siteactions li a { ... }
#portal-siteactions li.selected a { ... }
#portal-siteactions li a:hover { ... }
/* Searchbox style and positioning */
#portal-searchbox { ... }
#portal-advanced-search { ... }
#portal-advanced-search a { ... }
/* Search results elements */
dl.searchResults dt { ... }
form.searchPage { ... }
input.searchPage { ... }
form.searchPage input.searchButton { ... }
/* LiveSearch styles */
.LSRes { ... }
#LSHighlight, .LSHighlight { ... }
.LSRow { ... }
.LSRow a { ... }
.LSDescr { ... }
.LSResult { ... }
.LSShadow { ... }
.livesearchContainer { ... }
* html .livesearchContainer { ... }
#livesearchLegend { ... }
* html #livesearchLegend { ... }
/* Workaround for Internet Explorer's broken z-index implementation
*/
.LSIEFix { ... }
.LSBox { ... }
#LSNothingFound { ... }
.LSBox label { ... }
/* The global section tabs. */
#portal-globalnav { ... }
#portal-globalnav li { ... }
#portal-globalnav li a { ... }
#portal-globalnav li.selected a { ... }
#portal-globalnav li a:hover { ... }
/* Bar with personalized menu (user preferences, favorites etc) */
#portal-personaltools { ... }
#portal-personaltools .portalUser { ... }
/* Used on all descriptions relevant to those not logged in */
#portal-personaltools .portalNotLoggedIn { ... }
#portal-personaltools li { ... }
#portal-personaltools li a { ... }
#portal-personaltools .visualIconPadding { ... }
.visualCaseSensitive { ... }
#portal-languageselector { ... }
#portal-languageselector li { ... }
/* The path bar, including breadcrumbs and add to favorites */
#portal-breadcrumbs { ... }
#portal-breadcrumbs a { ... }
.breadcrumbSeparator { ... }
.addFavorite { ... }
.documentEditable { ... }
#content-news h1 { ... }
/* Only h5/h6 headlines in the content area should have the discreet
color */
#content h5, #content h6 { ... }
.newsItem { ... }
.newsImage { ... }
.newsImageContainer { ... }
.newsContent { ... }
.newsContent ul, .newsContent li { ... }
.newsAbout { ... }
.newsAbout li { ... }
.newsFooter { ... }
.newsFooter li { ... }
.documentActions { ... }
.documentActions ul { ... }
.documentActions li { ... }
.documentActions a { ... }
/* Status messages */
dl.portalMessage { ... }
dl.portalMessage a { ... }
dl.portalMessage dt { ... }
dl.portalMessage dd { ... }
dl.warning dt { ... }
dl.error dt { ... }
dl.warning dd { ... }
dl.error dd { ... }
/* The summary text describing the document */
.documentDescription { ... }
.documentByLine { ... }
dl.searchResults span.documentByLine { ... }
#category ul { ... }
#category ul li { ... }
.discussion { ... }
.even { ... }
.odd { ... }
.visualHighlight { ... }
.discreet { ... }
.pullquote { ... }
.callout { ... }
.notify, .documentEditable * .notify { ... }
.card { ... }
.card a { ... }
.portrait { ... }
.portraitPhoto { ... }
/* The table used for listings - horizontal and vertical variants */
table.listing, .stx table { ... }
table.listing th, .stx table th { ... }
table.listing .top { ... }
table.listing .listingCheckbox { ... }
table.listing td, .stx table td { ... }
table.listing a { ... }
table.listing a:hover { ... }
table.listing img { ... }
table.listing td a label, .stx table td a label { ... }
/* Vertical addition class */
table.vertical { ... }
table.vertical th { ... }
table.vertical td { ... }
/* grid addition class */
table.grid td { ... }
/* plain table class with light gray borders */
table.plain, table.plain td, table.plain th { ... }
/* Batch selector */
.listingBar { ... }
.listingBar span.previous, .listingPrevious { ... }
.listingBar span.next, .listingNext { ... }
.listingBar img { ... }
.listingBar a { ... }
.tileItem { ... }
.tileHeadline { ... }
.tileHeadline a { ... }
.tileBody { ... }
.tileImage { ... }
.eventDetails { ... }
/* Useful deviations from regular style on elements */
/* List classes without markers */
ul.visualNoMarker, ol.visualNoMarker { ... }
ul.discreet { ... }
textarea.proportional { ... }
.productCredits { ... }
#portal-footer { ... }
#portal-footer p { ... }
#portal-footer a { ... }
#portal-footer a:visited { ... }
#portal-footer a:hover { ... }
#portal-colophon { ... }
#portal-colophon ul { ... }
#portal-colophon ul li { ... }
#portal-colophon ul li a { ... }
.feedButton { ... }
.poweredBy { ... }
/* Sitemap styles */
#portal-sitemap { ... }
#portal-sitemap a { ... }
#portal-sitemap a:hover { ... }
#portal-sitemap .navTreeLevel1 { ... }
#portal-sitemap .navTreeLevel2 { ... }
/* Album view classes */
.photoAlbumEntry { ... }
.photoAlbumEntry img { ... }
.photoAlbumEntryWrapper { ... }
.photoAlbumEntry a { ... }
.photoAlbumFolder { ... }
.photoAlbumEntryTitle { ... }
/* Link types */
a.link-parent { ... }
#content .link-category { ... }
#content .link-user { ... }
#content .link-comment { ... }
#content .link-anchor { ... }
#content .link-presentation { ... }
#content .link-wiki-add { ... }
/* Handling external/internal links, we first set the icon on all
links, then
remove it from the ones that are local - for both http and https */
#content a[href ^="http:"], #content a.link-external { ... }
#content a[href ^="https:"], #content a.link-https { ... }
#content a[href ^="&dtml-portal_url;"] { ... }
/* Protocol-specific links */
#content a[href ^="mailto:"], #content a.link-mailto { ... }
#content a[href ^="news:"], #content a.link-news { ... }
#content a[href ^="ftp:"], #content a.link-ftp { ... }
#content a[href ^="irc:"], #content a.link-irc { ... }
#content a[href ^="callto:"], #content a.link-callto { ... }
#content a[href ^="webcal:"], #content a.link-webcal { ... }
#content a[href ^="feed:"], #content a.link-feed { ... }
#content .link-plain { ... }
/* For ghosted elements */
.visualGhosted { ... }
/* Fullscreen */
body.fullscreen #portal-logo, body.fullscreen #portal-siteactions {
... }
body.fullscreen #portal-globalnav { ... }
body.fullscreen #portal-searchbox { ... }
/* Kupu image alignment classes */
.image-left { ... }
.image-inline { ... }
.image-right { ... }
dd.image-caption { ... }
dl.captioned { ... }
/* Dashboard */
#dashboard-info-message { ... }
#dashboard { ... }
#dashboard-portlets1,
#dashboard-portlets2,
#dashboard-portlets3 { ... }
#dashboard-portlets4 { ... }
#dashboard-portlets1 a,
#dashboard-portlets2 a,
#dashboard-portlets3 a,
#dashboard-portlets4 a { ... }
#dashboard-portlets1 dl.portlet,
#dashboard-portlets2 dl.portlet,
#dashboard-portlets3 dl.portlet,
#dashboard-portlets4 dl.portlet { ... }
div.managedPortlet.portlet { ... }
#dashboard select { ... }
.portletAssignments { ... }
#dashboard-portlets1 div.managedPortlet a,
#dashboard-portlets2 div.managedPortlet a,
#dashboard-portlets3 div.managedPortlet a,
#dashboard-portlets4 div.managedPortlet a { ... }
#dashboard-portlets1 div.managedPortlet span a,
#dashboard-portlets2 div.managedPortlet span a,
#dashboard-portlets3 div.managedPortlet span a,
#dashboard-portlets4 div.managedPortlet span a{ ... }
#dashboard-actions { ... }
#dashboard-actions ul { ... }
#dashboard-actions ul li { ... }
#dashboard-actions ul li.portalUser { ... }
/* manage portlets */
.section div { ... }
Estilos para columnas de tabla-basada también conocido como “slot izquierdo”, “slot derecho”, etc.
#portal-columns { ... }
#portal-column-one { ... }
#portal-column-content { ... }
#portal-column-two { ... }
body.fullscreen #portal-column-one, body.fullscreen #portal-column-
two { ... }
body.fullscreen #portal-column-content { ... }
Estilos asociados con elementos de creación visible para los proveedores de contenido.
/* Editable border */
.contentViews { ... }
.contentViews li { ... }
.contentViews li a { ... }
.contentViews .selected a { ... }
.contentViews li a:hover { ... }
.configlet .contentViews { ... }
/* begin ECMAScript Content Action Menus */
.contentActions { ... }
.contentActions ul, .contentActions li { ... }
.contentActions li { ... }
.contentActions a { ... }
.contentActions span.subMenuTitle { ... }
.contentActions a span.subMenuTitle { ... }
.actionMenu { ... }
.actionMenu .actionMenuHeader { ... }
.actionMenu.activated .actionMenuHeader { ... }
.actionMenu .actionMenuHeader a { ... }
.arrowDownAlternative { ... }
.actionMenu .actionMenuContent { ... }
.actionMenu.activated .actionMenuContent { ... }
.actionMenu.activated .actionMenuContent { ... }
.actionMenu.deactivated .actionMenuContent { ... }
.actionMenu .actionMenuContent ul { ... }
.actionMenu .actionMenuContent li { ... }
.actionMenu .actionMenuContent li a { ... }
.actionMenu .actionMenuContent .selected { ... }
.actionMenu .actionMenuContent li a:hover { ... }
.actionMenu .actionMenuContent .actionSeparator a { ... }
#templateMenu li a { ... }
/* end ECMAScript Content Action Menus */
ul.configlets { ... }
ul.configlets li { ... }
ul.configlets li a { ... }
ul.configlets li a:visited { ... }
ul.configlets li a:active { ... }
ul.configlets li label { ... }
ul.configletDetails { ... }
ul.configletDetails li { ... }
ul.configletDetails li a { ... }
ul.configletDetails li label { ... }
/* Additional STX workaround classes */
.stx table p { ... }
.stx table { ... }
.stx table td { ... }
.reviewHistory { ... }
.comment { ... }
.comment h1, .comment h2, .comment h3, .comment h4, .comment h5,
.comment h6 { ... }
.comment h3 a { ... }
.commentBody { ... }
.spacer { ... }
/* Collapsible elements */
dl.collapsible { ... }
dl.collapsible dt.collapsibleHeader { ... }
dl.collapsible dd.collapsibleContent { ... }
/* for IE the following isn't needed, that's why the css2 selector is
used */
dl.collapsible dd.collapsibleContent > dl { ... }
dl.expandedInlineCollapsible dt.collapsibleHeader,
dl.expandedBlockCollapsible dt.collapsibleHeader { ... }
dl.collapsedBlockCollapsible { ... }
dl.collapsedBlockCollapsible dt.collapsibleHeader { ... }
dl.collapsedInlineCollapsible dd.collapsibleContent,
dl.collapsedBlockCollapsible dd.collapsibleContent { ... }
dl.collapsedInlineCollapsible { ... }
dl.collapsedInlineCollapsible dt.collapsibleHeader { ... }
.configlet .documentEditable { ... }
.documentEditable .documentContent { ... }
.label { ... }
.optionsToggle { ... }
#portal-column-content fieldset > * input:focus, #portal-column-
content fieldset > * textarea:focus { ... }
.highlightedSearchTerm { ... }
dl.searchResults .highlightedSearchTerm { ... }
.noInheritedRoles { ... }
.currentItem { ... }
tr.dragging td { ... }
.draggingHook { ... }
.notDraggable { ... }
.managePortletsLink { ... }
ul.formTabs { ... }
li.formTab { ... }
li.formTab a { ... }
li.formTab a { ... }
li.firstFormTab a { ... }
li.lastFormTab a { ... }
li.formTab a.selected { ... }
li.formTab a:hover { ... }
li.formTab a.notify { ... }
li.formTab a.required span { ... }
li.formTab a.notify:hover { ... }
.formPanel { ... }
.formPanel.hidden { ... }
div.formControls input.hidden { ... }
Estilos asociados con componentes de portlets individuales
/* Main portlet elements */
.portlet { ... }
.portlet a { ... }
.portlet a.tile { ... }
.portletItem a:visited, .portletFooter a:visited { ... }
.portletHeader { ... }
.portletHeader a { ... }
.portletItem { ... }
.portletItem ol { ... }
.portletItemDetails { ... }
.portletFooter { ... }
/* Elements that enable layout with rounded corners */
.portletTopLeft { ... }
.portletTopRight { ... }
.portletBottomLeft { ... }
.portletBottomRight { ... }
/* Calendar elements - used in the calendar rendering */
.dayPopup { ... }
.date { ... }
.portletCalendar { ... }
.portletCalendar dt { ... }
.portletCalendar dd { ... }
.portletCalendar a { ... }
.portletCalendar a:hover { ... }
.ploneCalendar { ... }
.ploneCalendar td { ... }
.ploneCalendar .weekdays th { ... }
.ploneCalendar .event { ... }
.ploneCalendar .todayevent { ... }
.ploneCalendar .todaynoevent { ... }
.managePortletsLink { ... }
div.portlets-manager div.section { ... }
div.managedPortlet { ... }
.managedPortlet .portletHeader { ... }
.managedPortlet a { ... }
.managedPortletActions { ... }
.managedPortletActions a { ... }
.managedPortletActions a.up,
.managedPortletActions a.down { ... }
.managedPortletActions a.delete { ... }
/* Table of Contents styling - essentially a portlet with smaller
fonts and aligned right + limited in width */
.toc { ... }
Estilos asociados con el panel de control de Plone
.inlineDisplay { ... }
table.controlpanel-listing { ... }
table.controlpanel-listing td, table.controlpanel-listing th { ... }
table.controlpanel-listing dl { ... }
table.controlpanel-listing dd { ... }
table.controlpanel-listing dl dt a .trigger{ ... }
table .controlpanel-listing td { ... }
table.controlpanel-listing td.checker{ ... }
table.controlpanel-listing th.smallcolumn { ... }
.chooser-right { ... }
.rule-element { ... }
.rule-element dl { ... }
.rule-element dl dd { ... }
.rule-updown, .rule-operations { ... }
Estilos de impresión para exploradores con capacidad CSS2. Gran parte de esta stylesheets (hoja de estilo) tiene que ver con esconder componentes considerados inapropiados para documentos impresos.
Estilos para elementos desacreditados o en desuso que desaparecerán de Plone en versiones futuras.
Estilos para los elementos invisibles y de accesibilidad.
/* List classes without markers */
ul.visualNoMarker, ol.visualNoMarker { ... }
.visualOverflow { ... }
.visualOverflow pre, .visualOverflow table, .visualOverflow img { ...
}
/* Accessibility and visual enhancement elements */
.hiddenStructure { ... }
.contentViews .hiddenStructure, .contentActions .hiddenStructure {
... }
.hiddenLabel { ... }
/* Helper element to work with CSS floats */
.visualClear { ... }
/* Hiding helper elements for old browsers */
.netscape4 { ... }
Estilos asociados con formularios.
textarea { ... }
input { ... }
input[type=checkbox] { ... }
#searchGadget { ... }
button { ... }
select { ... }
form { ... }
fieldset { ... }
legend { ... }
label { ... }
optgroup { ... }
option { ... }
optgroup > option { ... }
dl.enableFormTabbing dd { ... }
#login-form { ... }
#login-form .field { ... }
#login-form input { ... }
#login-form input.context { ... }
#forgotten-password { ... }
.standalone, .documentEditable * .standalone { ... }
.context, .formControls .actionButtons .button, .documentEditable *
.context { ... }
.destructive, .documentEditable * .destructive { ... }
input.searchButton { ... }
.searchSection { ... }
.searchSection label:hover { ... }
/* The edit form elements */
.field { ... }
.field .field { ... }
.fieldRequired { ... }
.fieldUploadFile { ... }
.fieldTextFormat { ... }
.formHelp { ... }
.formHelp:hover { ... }
div.error { ... }
.error .fieldRequired { ... }
/* Styles to make the editing widgets look more like their view
counterparts */
#archetypes-fieldname-title input, input#form\.title { ... }
#archetypes-fieldname-description textarea,
textarea#form\.description { ... }
input.inputLabelActive { ... }
textarea#form\.description { ... }
tr.selected { ... }
.kupu-save-message { ... }
No es accesible a través de Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles.
Aquí es donde sus estilos modificados localmente deben ir. Por defecto, ningún estilo se define en esta stylesheet.
No es accesible a través de Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles.
No es accesible a través de Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles.
No es accesible a través de Interfaz de Administración de Zope ‣ portal_skins ‣ plone_styles.
Skin layers
Plantillas, scripts, imágenes, CSS y archivos JavaScript se organizan con las capas del skin
A la piel se compone de una serie de capas del skin. En el sistema de archivos, cada capa es un directorio. En la Interfaz de Administración de Zope (ZMI), cada capa aparece en portal_skins como una carpeta separada (con plantillas de páginas, hojas de estilos o scripts de Python).
Estas tienen dos usos.
Para crear una capa del skin a través de la web, basta con agregar una nueva carpeta. En el sistema de archivos, agregue un directorio a su directorio del skin. También tendrá que agregar una pequeña cantidad de configuración para asegurarse de que su directorio es encontrado y registrado como una capa skin en la instalación.
Primero en [su paquete tema]/skins.zcml
<cmf:registerDirectory name="[Su nombre del directorio skin]"/>
Luego en [su paquete tema]/profiles/default/skins.xml
<object name="[Su nombre del directorio skin]"
meta_type="Filesystem Directory View"
directory="[su nombre de espacio].[su nombre del tema]:skins/[Su nombre del directorio skin]"/>
y
<skin-path name="[su nombre de skin]" based-on="Plone Default">
<layer name="[Su nombre del directorio skin]"
insert-after="custom"/>
</skin-path>
Cómo las capas del skin funcionan y cómo estas pueden ser usadas en la personalización.
Si usted ha trabajado con Plone 2, estará entonces familiarizado con este tipo de personalización. Como hemos mencionado anteriormente, el orden de capas en una skin determina cuales plantillas de página, archivos CSS y scripts de Python se procesen primero.
Para inspeccionar el orden de precedencia:
Usted debería ver las capas del skin por defecto de Plone que allá se listan. Capas como “plone_templates” provienen del tema principal de Plone, pero también habrá capas que proveen plantillas desde productos adicionales específicos (por ejemplo, el editor visual kupu).
Cuando se le pidió para procesar una plantilla específica, Plone trabajará desde arriba hacia abajo de la lista, buscando en cada capa a su vez para recuperar la plantilla.
En la parte superior hay una capa personalizada; cualquier plantilla colocada aquí se encontrará y se utilizará de primero. Por lo tanto, para crear su propia versión de una plantilla de Plone o archivo CSS, dele el mismo nombre que la versión de Plone pero póngalo en la capa personalizada.
Este es el enfoque más simple, pero el hecho de garantizar que la versión está en un capa superior en el orden de precedencia en un skin que el tema principal de Plone será suficiente para asegurar que Plone lo encuentre primero e ignore la versión original.
Esta técnica se puede utilizar de dos maneras:
utilizando la carpeta personalizada a través de la Interfaz de Administración de Zope, usted puede agregar sus propias versiones de plantillas, hojas de estilo, etc en la carpeta personalizada. Esto siempre se produce en la parte superior, por lo que puede estar seguro que sus versiones se encontrarán primero. agregando sus propias capas skin en su propio producto de tema en el sistema de archivos, cree una o dos capas skin, y asegúrese que en la instalación estas capas están puestas justo debajo de la carpeta personalizada en el orden o precedencia. Hay más información sobre cómo hacer esto en la siguiente sección.
Probablemente la descripción más completa de skins, capas y orden de precedencia puede encontrarse en las primeras dos secciones del Capitulo 7 de la guía definitiva para Plone (note que la mayoría de este libro hace referencia a Plone 2, pero estas secciones siguen siendo relevantes para Plone 3).
¿Cómo se crea realmente un skin?
Si usted utiliza la plantilla paster plone3_theme, el código lo proporcionará, cuando el producto de tema está instalado, lo cual registrará los directorios del skin como capas skins y las reunirá en una skin nueva.
La plantilla paster le da la opción de basar su skin en el Plone Default. Esto es, cuando instala el tema en su sitio, las capas skins de Plone serán añadidas a las suyas, pero por debajo de las suyas en el orden de precedencia. Esta es una buena idea, para luego reusar detalles de Plone Default sin duplicarlos, y sustituir aquellos que no quiera.
Los pasos clave son:
Registre los directorios de su skin como Filesystem Directory Views “Vistas de directorios del sistema de archivos”, para que se puedan convertir en capas skin. Esto ocurre en dos sitios:[su paquete del tema]/skins.zcml y [su paquete tema]/profiles/default/skins.xml
<cmf:registerDirectory name="[Su nombre del directorio skin]"/>
<object name="[Su nombre del directorio skin]"
meta_type="Filesystem Directory View"
directory="[su nombre de espacio].[su nombre del tema]:skins/[Su nombre del directorio skin]"/>
Agregue y organice sus capas skins dentro de una sola skin [su paquete del tema]/profiles/default/skins.xml
<skin-path name="[su nombre de skin" based-on="Plone Default">
<layer name="[Su nombre del directorio skin]"
insert-after="custom"/>
</skin-path>
Defina su skin como la skin por defecto [su paquete del tema]/profiles/default/skins.xml empaquetando este nodo alrededor de los nodos de los dos ejemplos anteriores.
<object name="portal_skins" allow_any="False" cookie_persistence="False"
default_skin="[su nombre de skin]">
.........
</object>
El nombre de su skin es requerido en algunos sitios en su producto de tema. Vale la pena conocer dónde y por qué, para referencia, las ocurrencias figuran en esta lista.
Dónde | Atributos/Directivas utilizados/as | Uso |
---|---|---|
profiles/default/skins.xml | <skin_path name=”[su nombre de skin]” | Usado para nombrar el conjunto de capas skin |
profiles/default/skins.xml |
|
Usado para definir su grupo de capas skin como el skin por defecto. |
browser/configure.zcml | <interface ... name=”[su nombre de skin]” /> | Usado para nombrar la interfaz específica de tema (vea la sección de Componentes) |
profiles/default/viewlets.xml |
|
Usado para especificar el tema cuando ordena los viewlets en el administrador de estos. (Vea la sección de Componentes) |
La decoración de la página, viewlets, portlets, y sus respectivos administradores. Cómo hacer el suyo propio y cómo encontrar las cosas que necesita.
Información sobre componentes y cómo están conectados entre sí.
Componentes son herramientas potentes y flexibles de Plone 3, pero un poco más abstracto que las plantillas de página o scripts de Python. Como el diagrama arriba intenta mostrar, estos son normalmente combinaciones de clases Python y plantillas de páginas conectadas entre sí en el Lenguaje de Marcado de Configuración Zope (ZCML) y con un nombre dado.
Hay dos cosas importantes para recordar acerca de los componentes
Los componentes son combinados de clases, plantillas, interfaces, permisos, etc. Para hacer un seguimiento de componentes usted necesita buscar en primer lugar en los archivos. ZCML, localizar sus nombres, y esto le llevará a las clases y plantillas que contribuyen a ellos. Los Componentes llegan a existencia cuando la instancia de Zope es iniciada A condición de que Zope haya leído el archivo .zcml, un componente estará disponible para su uso. No es posible sobrescribir los componentes existentes, es mejor que cree la suya propia, reusando algunas de las partes.
Un componente llega a existir a través de una “directiva” ZCML (hay un ejemplo de una de estas más adelante). La directiva tendrá un serie de “atributos” los cuales apuntarán a las diferentes piezas que intervienen en su creación. Estas piezas tienen cuatro funciones principales.
Hay más sobre esto en la sección de partes de componentes
El Five Tutorial on WorldCookery.com lo guiará a través del ZCML, y hay suficientes ejemplos en los tutoriales en el sitio de documentación de Plone.
Aquí está una directiva de muestra ZCML evocando el viewlet de presentación (que simplemente ofrece un enlace a una versión de presentación de una página):
<configure xmlns="http://namespaces.zope.org/zope" xmlns:browser="http://namespaces.zope.org/browser"> <browser:viewlet name="plone.presentation" for="Products.ATContentTypes.interface.IATDocument" manager="plone.app.layout.viewlets.interfaces.IAboveContentBody" class=".presentation.PresentationViewlet" permission="zope2.View" /> </configure>
Hay tres cosas que destacar:
Puede obtener información detallada sobre las directivas ZCML en la sección de Referencia de ZCML de la API (Interfaz de programación de aplicaciones) para Zope 3 - http://apidoc.zope.org/++apidoc++/. Si usted quiere ser muy disciplinado y ordenado, consulte la ZCMLStyleGuide http://wiki.zope.org/zope3/ZCMLStyleGuide .
Tipos de componentes.
Esta es una nueva característica de Plone 3 y se utiliza para proporcionar los aspectos de la decoración de la página; los elementos de la página que por lo general no cambian en las áreas del sitio. Estos son organizados por otro tipo de contenido; un Administrador de Viewlet.
Para más información puede revisar:
Los Portlets en Plone son cajas de información, usualmente en la columnas de izquierda o derecha de una página, que contienen contenido agregado o información adicional, que puede ser directamente relevante o no al elemento de contenido que se está mostrando. Tras bambalinas estás se solían construir de plantillas de páginas ordinarias, pero ahora en Plone 3, estos son conectados en conjunto como componentes y manejadas por otro componente: un Administrador de Portlet.
Para más información echa un vistazo a:
Ya hemos dado una definición del término “vista” en la sección de skin anterior. Sin embargo, tras bambalinas, en el contexto de componentes, Vista tiene un significado más técnico. Se refiere a un componente el cual es regularmente creado de una clase Python o una plantilla o incluso ambas, en pocas palabras, procesa los datos desde un elemento de contenido antes de que llegue a la página. Hay una explicación técnica en el Manual de Desarrollo de Plone.
A veces verá que es referida como BrowserView (Vista de Explorador) o <browser:page> y en plantillas usted verá el nombre de vista del navegador precedido por @@. Nos fijamos en las vistas del explorador una vez más en la sección de armar una página.
Nota
Tenga en cuenta que el término explorador y namespace del explorador son usados para demarcar componentes de presentación; esto es, esas partes de códigos que se usan para crear elementos las cuales encontrarán el camino al navegador Web en algún momento.
Aunque hemos indicado que el skin y las capas son el hogar habitual de plantillas de páginas, imágenes y hojas de estilo, también es posible convertirlas en componentes mediante su registro en ZCML. En este caso las verá referidas así ++resource++[nombre del recurso]. Lo mismo se puede hacer para un directorio que contiene las plantillas y hojas de estilo.
En este momento puedo escuchar que está diciendo “Genial” y “¿cual debería usar, componentes o skins?”, vaya a la sección ¿Skin o Componentes? para una discusión de los pros y contras. Al momento de escritura sugerimos la opción más sencilla que es mantener sus plantillas, imágenes y hojas de estilo en su skin. Estamos mencionando los recursos del explorador para que sepa que son en el caso de encontrárselos.
Usted puede personalizar a través de la Web, pero en el sistema de archivos la manera para personalizar o crear componentes para su tema es conectar nuevos.
Al igual que para skins y capas, es posible personalizar las plantillas usadas por componentes a través de Interfaz de Administración de Zope.
Usted necesitará saber el nombre de su componente (por ejemplo plone.presentation). La sección Elementos de este manual le ayudará en el caso de que el nombre no sea obvio. Solo puede reescribir las plantillas, lo cual puede ser limitante.
Usted puede lograr mucho más si está construyendo su propio tema en el sistema de archivos, y en este caso el enfoque es ligeramente diferente.
En vez de reescribir un componente (como puede hacer para el skin), es mucho más fácil crear su propia versión. Esto involucra un poco de reestructuración o nueva estructuración en su propio archivo .zcml, pero realmente es más sencillo de lo que parece.
He aquí un ejemplo de la viewlet de presentación, ya que es utilizado por Plone:
<browser:viewlet
name="plone.presentation"
for="Products.ATContentTypes.interface.IATDocument"
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
class=".presentation.PresentationViewlet"
permission="zope2.View"
/>
Imagine para sus propósitos, que necesita usar una nueva clase para obtener este viewlet como usted quiere. En su propio archivo configure.zcml, dele un nuevo nombre y conéctelo a su propia clase.
<browser:viewlet
name="[su nombre de espacio].[su viewlet de presentación]"
for="Products.ATContentTypes.interface.IATDocument"
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
class=".[su modulo de viewlet].[su clase viewlet]"
permission="zope2.View"
/>
Más información sobre algunas de las piezas que sirven para constituir los componentes.
Interfaces son un tema un poco tecnológico y algo que una persona que no sea desarrolladora preferiría evitar. No obstante, son una parte importante de las conexiones (estructuras) de un componente, así que vale la pena saber un poco que son y que hacen.
Atributos ZCML a menudo se refieren a las interfaces en lugar de clases, por ejemplo, el siguiente ejemplo conecta el viewlet de presentación de los tipos de contenido que tienen la interfaz IATDocument.
<browser:viewlet
name="plone.presentation"
for="Products.ATContentTypes.interface.IATDocument"
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
class=".presentation.PresentationViewlet"
permission="zope2.View"
/>
En efecto esto se traduce en que el viewlet de presentación está disponible para cualquier tipo de contenido que sea un ATDocument o se comporta como un ATDocument. Por lo tanto, en este caso, la interfaz es un marcador.
Lo conveniente de esto es que un tipo de contenido puede tener una o más interfaces. y varios tipos de contenido pueden compartir las misma interfaz. Si usted desarrolla un nuevo tipo de contenido y lo marca con una interfaz IATDocumen, usted puede usar este viewlet de presentación dentro de él: sin extra conexiones (estructuración) requerida.
Los componentes se pueden marcar con una interfaz, el término técnico es “proporcionar”. Tenga en cuenta que en el ejemplo de viewlet de presentación, el administrador de viewlet es referido por su interfaz, y no por su Nombre:
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
Para localizar el componente, busque en el archivo configure.zcml en el mismo directorio que las interfaces. Por ejemplo en plone/app/layout/viewlets/configure.zcml verá que la interfaz ha sido conectada con una clase Python para crear un componente de administrador de viewlet:
<browser:viewletManager
name="plone.abovecontentbody"
provides=".interfaces.IAboveContentBody"
permission="zope2.View"
class="plone.app.viewletmanager.manager.OrderedViewletManager"
/>
Generalmente es bastante fácil detectar una referencia a una interfaz. Por convención sus nombres tendrán el prefijo “I” y estarán alojados en una interfaz o namespace de la interfaz. Si usted investiga interfaces.py o interface.py en cualquier huevo o producto, no encontrará mucha cantidad de código, pero a menudo encontrará información útil. Efectivamente es documentación sobre lo que un componente que está proporcionando (es decir marcado por) esa interfaz debería hacer. Por ejemplo:
class IAboveContentBody(IViewletManager):
"""A viewlet manager that sits above the content body in view
templates """
Si ha utilizado la plantilla de paster plone3_theme, usted encontrará que tiene un archivo interfaces.py ya hecho, en donde puede agregar sus propias interfaces en el caso de que sea necesario crearlas.
Habrá notado que las clases de Python a menudo son parte de las conexiones entre componentes, y entenderá que realmente no puede evitar tener un poco de conocimiento acerca de ellas, especialmente si quiere crear sus propios viewlets.
Tener que lidiar con algo tan avanzado como las clases Python puede ser desalentador para el aquel no-desarrollador. La buena noticia es que el uso de clases Python será más un asunto de copiar y cambiar pequeñas partes de código que escribir desde cero.
Lo mejor es pensar en una clase como una pieza discreta de código que contiene una colección de métodos (“acciones” de algún tipo) y atributos (“variables” que pueden contener un valor).
En el caso de componentes, el objetivo principal de una clase es computar las partes de información que un componente necesita mostrar. La clase del viewlet de logotipo es un buen ejemplo. Puede encontrarlo en:
Después de un poco de trabajo preparatorio, la clase LogoViewlet primero averigua el nombre de la imagen que se va a utilizar para el logotipo (y se define en la hoja de propiedades base_properties):
logoName = portal.restrictedTraverse('base_properties').logoName
Luego resuelve las estadísticas vitales, tamaño, alt text (texto alternativo) etc y lo convierte en una etiqueta de anclaje HTML:
self.logo_tag = portal.restrictedTraverse(logoName).tag()
Finalmente, en el caso de que sea necesario, busca el título del sitio:
self.portal_title = self.portal_state.portal_title()
En la plantilla de página asociada con este viewlet puede hacerse con esta información (self.logo_tag, self.portal_title) usando la variable “view”:
<img src="logo.jpg" alt=""
tal:replace="structure view/logo_tag" />
Los viewlets tienden a estar conectados con una clase Python que apunta a una plantilla. Así que, aunque es posible que sólo desea crear una nueva plantilla, usted descubrirá que tiene que escribir una clase para que apunte a su nueva plantilla. La sección Elementos de este manual debería ayudarlo dándole un fragmento de código para que cada elemento copie y pegue dentro de su propio producto.
Aquí hay un ejemplo: La plantilla de logotipo estándar en realidad no hace uso de view/portal_title. Así que si usted quería incorporar esto de alguna manera en su logotipo, entonces usted tendrá que escribir su propia plantilla y también su propia clase:
from plone.app.layout.viewlets.common import LogoViewlet
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class [su nombre de clase](LogoViewlet):
render = ViewPageTemplateFile('[nombre de su plantilla]')
Si se siente valiente o quiere saber más, una introducción clara se puede encontrar aquí:
El atributo de permiso se puede usar para restringir la visibilidad de un componente.
Cuando un usuario inicia sesión en un sitio, se le dará cierto rol (“administrador”, “editor”, etc.) Este rol, efectivamente, es un conjunto de permisos, que otorgan derechos particulares sobre ciertos aspectos del sitio.
Para saber más sobre permisos consulte el tutorial para el entendimiento de permisos y seguridad:
En el caso de componentes, el atributo de permiso permite al sitio decidir si un usuario tiene un derecho (permiso) para ver o interactuar con un componente. La mayoría de viewlets tiene los permisos Zope2.View o Zope2.Public, los cuales se asignan a todo el mundo, incluso usuarios anónimos. Sin embargo observe el viewlet Lock info (información de bloqueo)
<browser:viewlet
name="plone.lockinfo"
manager=".interfaces.IAboveContent"
class="plone.locking.browser.info.LockInfoViewlet"
permission="cmf.ModifyPortalContent"
for="plone.locking.interfaces.ITTWLockable"
/>
Al usar cmf.ModifyPortalContent, este viewlet está restringido, es decir, se limita a sólo aquellos usuarios que tienen derecho de editar contenido (aquellos que no lo posean no estarán interesados si un elemento está bloqueado o no).
La lista de permisos disponibles está enterrada profundamente en el producto FIVE, el cual viene con la instalación de Zope, revise en permissions.zcml para la lista más actualizada.
Permisos | Descripción |
---|---|
zope2.Public | público, cualquiera puede acceder |
zope2.Private | Privado, sólo accesible desde código de confianza |
zope2.AccessContentsInformation | Acceder a información de contenido |
zope2.ChangeImagesFiles | Cambiar Imágenes y Archivos |
zope2.ChangeConfig | Cambiar configuración |
zope2.ChangePermissions | Cambiar permisos |
zope2.CopyOrMove | Copiar o Mover |
zope2.DefinePermissions | Definir permisos |
zope2.DeleteObjects | Eliminar objetos |
zope2.FTPAccess | Acceso FTP |
zope2.ImportExport | Importar/Exportar objetos |
zope2.ManageProperties | Administrar propiedades |
zope2.ManageUsers | Administrar usuarios |
zope2.Undo | Deshacer cambios |
zope2.View | Vista |
zope2.ViewHistory | Ver historial |
zope2.ViewManagementScreens | Ver pantallas de administración |
zope2.WebDAVLock | WebDAV Lock items (elementos de bloqueo WebDAV) |
zope2.WebDAVUnlock | Elementos desbloqueados WebDAV |
zope2.WebDAVAccess | Acceso WebDAV |
cmf.ListFolderContents | Listar contenido de carpetas |
cmf.ListUndoableChanges | Listar cambios infactibles |
cmf.AccessInactivePortalContent | Acceso a contenido inactivo del portal |
cmf.ManagePortal | Administrar portal |
cmf.ModifyPortalContent | Modificar contenido del portal |
cmf.ManageProperties | Administrar propiedades |
cmf.ListPortalMembers | Listar miembros del portal |
cmf.AddPortalFolders | Agregar carpetas de portal |
cmf.AddPortalContent | Agregar contenido de portal |
cmf.AddPortalMember | Agregar miembro de portal |
cmf.SetOwnPassword | Definir su propia contraseña |
cmf.SetOwnProperties | Definir sus propiedades |
cmf.MailForgottonPassword | Envío por correo de contraseñas olvidadas |
cmf.RequestReview | Solicitar revisión |
cmf.ReviewPortalContent | Revisión de contenido de portal |
cmf.AccessFuturePortalContent | Acceso a contenido futuro de portal |
Quizá usted quiere hacer componentes que sólo están disponibles para su tema particular. Para hacer esto necesitará una interfaz.
En la medida que los componentes entren en existencia en el momento que Zope inicie y lea los archivos .zcml, estarán disponibles para cada sitio Plone que usted tenga en la su instancia Zope. Tal vez usted no quiere que esto pase.
Usted puede especificar que sus componentes están disponibles sólo para su tema con una interfaz de marcador y un atributo de capa en ZCML. Aquí hay una versión re-conectada (reestructurada) del viewlet de presentación:
<browser:viewlet
name="[su nombre de espacio].[su viewlet de presentación]"
for="Products.ATContentTypes.interface.IATDocument"
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
class=".[su modulo de viewlet].[su clase viewlet]"
layer=".interfaces.IThemeSpecific"
permission="zope2.View"
/>
Hay dos métodos para crear una interfaz de tema:
En Plone 3.0, plone.theme es usado:
from plone.theme.interfaces import IDefaultPloneLayer
class IThemeSpecific(IDefaultPloneLayer):
"""Marker interface that defines a Zope 3 browser layer.
"""
<interface
interface=".interfaces.IThemeSpecific"
type="zope.publisher.interfaces.browser.IBrowserSkinType"
name="[su nombre de skin]"
/>
En Plone 3.1, plone.browserlayer está disponible para usted.
from zope.interface import Interface
class IThemeSpecific(Interface):
"""A layer specific to my product """
<layers>
<layer name="[su nombre de skin]"
interface="[su nombre de espacio].[su nombre del tema].browser.interfaces.IThemeSpecific"
/>
</layers>
Si usted genera su producto de sistema de archivo o huevo utilizando la plantilla paster plone3_theme, pues lo básico estará hecho para usted (usando el método plone.theme), simplemente tendrá que localizar la interfaz para encontrar su respectivo nombre. Busque en
Y debería encontrara el nombre IThemeSpecific. Cuando se refiera a ella, use esta ruta
layer=".interfaces.IThemeSpecific"
Habrá notado que usted puede convertir cualquier plantilla, archivo css, o cualquier directorio que contenga estos en un componente. Así que ¿por qué molestarse con el bloque para construcción de skin?
El producto creado por la plantilla de paster plone3_theme hace lo siguiente:
Este manual sugiere poner todas sus plantillas, hojas de estilo e imágenes en la sección de Skin, y dejar sólo las plantillas de viewlets y portlets en los componentes. Hay varias razones para esto
Al momento de estar escribiendo esto hay una gran discusión tratando de resolver esta pregunta.
Si usted quiere quitar los recursos del explorador fuera del producto creado por la plantilla paster plone3_theme
En dónde colocar los componentes de su propio producto y la manera de rastrearlos en la interfaz de Administración de Zope, y en el sistema de archivos.
Las plantillas para la mayoría de componentes pueden ser personalizadas a través de la web:
La sección Elementos le puede ayudar a identificar el componente que usted necesita.
Si usted está planeando conectar sus propios componentes, puede que sea necesario localizar los archivos relevantes de componentes existentes para copiarlos. Esto puede tener cierto grado de dificultad, Estos están empaquetados en un número de huevos distintos, por lo que necesita primero localizar dónde se almacenan los huevos, y luego averiguar cuál de estos contiene los elementos de componentes que necesita.
¿Cómo escribir un archivo de configuración y dónde ponerlo?
Configuración y los perfiles
La configuración se refiere al comportamiento predeterminado de un sitio (por ejemplo, si usted permite que las personas se registren en su sitio, o cómo se muestran las fechas). Es probable que quiera que algo de este comportamiento sea incorporado en su tema.
También hay cierta coincidencia entre los componentes, skins, y configuración. Por ejemplo, el orden de las capas del skin y el orden en que aparecen los viewlets dentro de un administrador de viewlet se consideran aspectos para la configuración.
Un perfil es un conjunto de archivos de configuración. Cada archivo está escrito en un XML bastante simple y hace referencia a un grupo en particular de componentes o elementos de página. Hay dos tipos diferentes de perfiles: perfiles de base y perfiles de extensión. Para fines de temas el único que usted necesitará es el perfil de extensión (es decir, un perfil que extiende la configuración de un sitio existente).
Un perfil aparece cuando se conecta mediante ZCML. Aquí está la versión creada por la plantilla de paster plone3_theme:
<genericsetup:registerProfile
name="default"
title="[su nombre de skin]"
directory="profiles/default"
description='Extension profile for the "[su nombre de skin]" Plone theme.'
provides="Products.GenericSetup.interfaces.EXTENSION"
/>
verá que apunta a un directorio para la ubicación de los archivos XML e indica que se trata de un perfil de extensión mediante el uso de una interfaz.
El lenguaje utilizado para definir los perfiles.
El XML utilizado para los archivos de perfil es sencillo. No hay ningún DTD disponible, pero hay una cantidad de ejemplos para reusarlos o adaptarlos para sus propósitos. Si todo esto parece demasiado, la buena noticia es que puede conseguir que Generic Setup escriba los archivos por usted exportando la configuración de un sitio existente. Hay más información sobre cómo hacer esto en la página de herramienta Generic Setup.
El nodo root de un perfil XML es por lo general un objeto:
<object name="portal_javascripts" meta_type="JavaScripts Registry">
.......
</object>
pertenece a una herramienta de sitio en particular (en este caso el registro JavaScripts). Sub-nodos representan sub-objetos y atributos XML corresponden a los atributos de esas clases.
<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" id="jquery.js"
inline="False"/>
Así que en este caso, el sub-nodo representa una entrada en el registro JavaScripts y sus casillas de verificación.
En el caso muy improbable de que sea necesario que averigüe por sí mismo que atributos usar, tendrá que investigar la API (o las interfaces y clases) de la herramienta en cuestión. Use http://api.plone.org o revise el código fuente.
Esta herramienta se utiliza para aplicar perfiles a su sitio.
La puede encontrar aquí
Puede ejecutar la herramienta manualmente, pero para efectos de temas, si ha creado un producto usando la plantilla de paster plone3_theme, Generic Setup será activada automáticamente cuando instale su tema en su sitio.
Encontrará información más extensa acerca de la herramienta Generic Setup en este tutorial:
Sin embargo, hay dos datos útiles que valen la pena conocerlos.
Aunque se puede desinstalar su tema usando portal_quickinstaller, en la actualidad, no puede deshacer los perfiles que Generic Setup aplicá durante la instalación. En la mayor parte esto no es un problema, pero puede ser confuso. Por ejemplo si está experimentando con el orden de sus viewlets y ha probado varias versiones de viewlets.xml en instalaciones sucesivas. En este caso, la exportación de un perfil (explicado más adelante) le puede ayudar a dar sentido a lo que ha hecho.
Puede exportar la configuración actual de su sitio como un conjunto de archivos XML. Esto puede ser útil si no está muy seguro de lo que ha hecho, si está buscando un perfil para basar su propia configuración, o si simplemente desea que la herramienta Generic Setup escriba una configuración para usted.
No siempre es obvio cuál step necesita exportar para obtener la exacta configuración que desea, es posible que tenga que experimentar.
Cómo funciona la configuración a través de la web y cómo localizar los archivos en el sistema de archivos.
Hay una serie de rutas diferentes para configurar su sitio a través de la web. La sección Elementos de este manual debe proporcionarle algunos consejos sobre dónde buscar para configurar ciertos elementos de página. En general
Usted encontrará mayoría de los archivos de configuración que usted necesita en:
Sin embargo, tenga en cuenta que algunos archivos de configuración pueden estar ubicados en productos de terceros. Por ejemplo, si desea añadir algunos estilos al editor visual Kupu, como parte de su tema, entonces necesitará kupu.xml el cual encontrará en [su locación de producto]/kupu/plone/profiles/default.
Hay una alternativa para cazar en el sistema de archivos, y esta es utilizar la herramienta Generic Setup para exportar el perfil.
El código fuente de este archivo esta hospedado en GitHub. Todos pueden actualizar y corregir errores en este documento con unos clic - sin necesidad de descargar.
Para mas información básica acerca de como actualizar este manual y referencia a sintaxis Sphinx, por favor consulte la guía Escribiendo y actualizando el manual.