Skinning con z3c.layout, z3c.pagelet, e z3c.template
Dipendenze
Prima le cose importanti, dobbiamo includere la configurazione per le nuove dipendenze che avremo con lo skinning. Aprite src/zcontact/configure.zcml e aggiungete <include package="z3c.pagelet" file="meta.zcml" /> verso la cima con il resto dei meta include. Qusto ci darà la nuova direttiva zcml z3c:pagelet. In fondo potrete quindi aggiungere due ulteriori include:
<include package="z3c.pagelet" /> <include package="zope.contentprovider" />
Creiamo un Layout
Ora andiamo alla parte interessante. Possiamo creare quello che viene chiamato un layout, che è simile a una macro, ma molto più semplice. Invece di avere una macro complicata che ogni pagina deve usare (con use-macro e fill-slot), possiamo semplicemente creare un page template con un tag particolare impostato a parte per il contenuti delle pagine reali. Possiamo usare layout diversi per skin differenti, e perfino per interfacce degli oggetti differenti. Pronti! Aprite il file src/zcontact/layout.pt e fatelo assomigliare a qualcosa di simile a questo (sentitevi liberi di essere creativi):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>ZContact</title>
<style type="text/css">
<!--
* {
margin: 0;
padding: 0;
}
body {
padding: 1em;
}
#content{
border: 1px solid #999;
padding: 1em;
background: #eee;
}
-->
</style>
</head>
<body>
<h1>ZContact</h1>
<!-- THE MAGIC HAPPENS IN THE LINE BELOW -->
<div id="content"
tal:content="structure provider:pagelet">Page Content</div>
<i>ZContact Tutorial Application</i>
</body>
</html>
Notate in particolare la linea verso il fondo che dice:
<!-- THE MAGIC HAPPENS IN THE LINE BELOW -->
<div id="content"
tal:content="structure provider:pagelet">Page Content</div>
Come potete immaginare, qui avviene la magia. La parte provider:pagelet dice a zope di cercare un content provider chiamato pagelet, che attraverso z3c.pagelet finisce per essere il contenuto per la pagina che vogliamo ottenere, che sia un form o un altro page template. Quindi è piuttosto potente, ma ora dobbiamo registrare questo layout per la nostra skin in zcml. Aprite zcontact/skin.zcml e aggiungete la seguente direttiva, piuttosto auto esplicativa:
<z3c:layout
for="*"
layer="zcontact.layer.IZContactBrowserLayer"
template="layout.pt"
/>
Inoltre, non dimenticate di aggiungere il namespace xml z3c al tag configure con xmlns:z3c="http://namespaces.zope.org/z3c".
Usiamo i Layout con Pagelet (e Template)
Ora che abbiamo il nostro layout, dobbiamo leggermente modificare le nostre pagine esistenti in modo da fargli usare effettivamente il nuovo meccanismo di layout. Il primo passo consiste nell'aprire zcontact/browser/configure.zcml e aggiungere il namespace xml z3c al tag configure: xmlns:z3c="http://namespaces.zope.org/z3c". Ora, dovunque stat usando un tag page, sostituite il tag page con z3c:pagelet senza cambiare altro. Siamo al 90% del nostro lavoro. L'unico avvertimento con le pagelet che le rende veramente diverse dalle normali pagine è che non hanno nulla a che pare con i page template. La direttiva pagelet non accetta un attributo template e richiede un attributo class. Per la maggior parte delle nostre pagine, costituite solo da form auto-generate, questo non è un problema. Tuttavia per la pagina iniziale vogliamo il nostro template.
Iniziamo sostituendo l'ultima direttiva per la pagina iniziale con quanto segue:
<z3c:pagelet
name="index.html"
for="zope.app.folder.interfaces.IRootFolder"
permission="zope.Public"
layer="zcontact.layer.IZContactBrowserLayer"
class=".contact.FrontPage"
/>
Notate che ho eliminato l'attributo template e aggiunto l'attributo class per la nostra classe FrontPage ancora da scrivere. Scriviamo questa classe in modo da completare questa nostra conversione. Aprite zcontact/browser/contact.py e in fondo aggiungete:
class FrontPage(BrowserPagelet):
"""Pagelet for the front page."""
mettendo in cima al file from z3c.pagelet.browser import BrowserPagelet.
A questo punto dovreste pensare "che è successo al nostro page template e questa classe sembra inutile". Malgrado non abbia nessuna reale sostanza, questa classe fa abbastanza poichè eredita da BrowserPagelet. La classe BrowserPagelet fornisce uno speciale metodo __call__ che usa un adattatore per agganciare il.. template.
Potreste dire "un adattatore per agagnciare il template? Significa che posiamo registrare template diversi per la stessa page(let)?" la risposta è un sonoro sì. Possiamo specificare il template per la pagelet nella sua classe (usando template = ViewPageTemplateFile('frontpage.pt')), o possiamo registrare un template da usare per una specifica skin tramite zcml. Lo faremo più tardi a fini dimostrativi.
tornate a zcontact/browser/configure.zcml e aggiungete la seguente direttiva proprio sotto la pagelet della pagina iniziale:
<z3c:template
template="frontpage.pt"
for=".contact.FrontPage"
layer="zcontact.layer.IZContactBrowserLayer"
/>
Usiamo i Layout con dei Form
C'è ancora un punto rimasto prima che la nostra applicazione possa essere considerata bella e pronta. Il paccheto z3c.form è stato architettato in modo tale da poter essere usato senza tutta questa nuova questione di layout e pagelet (buona cosa). Fortunatamente il pacchetto z3c.formui fornisce supporto ai layout con il suo modulo form.
Per convertire le nostre form esistenti a usare il meccanismo del layout dobbiamo solo manipolare i nostri import in modo da usare from z3c.formui import form al posto di from z3c.form import form. Gli import che sono in cima a zcontact/browser/contact.py dovebbero ora apparire così:
from z3c.form import field, button from z3c.form.interfaces import DISPLAY_MODE from z3c.formui import form from z3c.pagelet.browser import BrowserPagelet from zope.traversing.browser.absoluteurl import absoluteURL from zope.traversing.api import getParent, getName from zcontact import interfaces from zcontact.contact import Contact
Questo conclude la nostra conversione di skin, quindi dovreste essere in grado di riavviare il web server e saltare a bordo di una bella skin (a meno che non abbiate risolutamente copiato il mio CSS). Ecco delle screenshot delle nostre nuove pagine:

