5. Introduzione al Plone Templating
Capitolo 5: Introduzione alla modellazione in Plone (Plone Template)
- Comprendere il meccanismo di modellazione sottostante
- Usare il sistema dei modelli di pagina Zope Page Templates
- Capire la sintassi di base dei modelli di pagina
- Introduzione alle variabili Built-in
- Introduzione alla sintassi delle espressioni TAL
- tal:attributes: modificare gli attributi di un elemento
- tal:condition: valutare condizioni
- tal:content: aggiungere del testo
- tal:define: definire variabili
- tal:omit-tag: rimuovere elementi
- tal:on-error: effettuare la gestione degli errori
- tal:repeat: realizzare iterazioni
- tal:replace: aggiungere del testo
- Introduzione all'ordine di esecuzione
- Esempio: visualizzare informazioni sull'utente
Plone utilizza tre livelli di tecnologie per creare una pagina. Del codice Python e i modelli di pagina [1] creano l'Hypertext Markup Language [2] o HTML che è inviato al browser. Quindi alcuni Cascading Style Sheets [3] (CSS) applicano le regole di formattazione che producono la pagina con la quale il lettore è adesso famigliare. Questi due primi elementi, il codice Python e i modelli di pagina, sono l'argomento principale di questo capitolo e del Capitolo 6.
Per capire come creare e quindi modificare un modello di pagina Plone è necessario prima descrivere alcuni concetti di base. Alcuni di questi concetti sono caratteristiche particolari di Plone e nonostante introducano grandi vantaggi è necessario un po' di tempo per prendervi confidenza.
In questo capitolo cominceremo con descrivere la pubblicazione di oggetti. Spiegheremo come interagire con gli oggetti all'interno di Plone, quindi descriveremo come costruire espressioni. Una volta che il lettore sarà familiare con questi due concetti analizzeremo come le pagine di Plone sono realmente assemblate. Alla fine del capitolo creeremo una nuova pagina all'interno del nostro sito Plone con le tecniche fino lì imparate.
Questo capitolo ha più significato per il lettore che è già familiare con il linguaggio Python. Tuttavia ad ogni passo verranno spiegati i concetti che stanno dietro al codice quindi, anche se il lettore non conosce Python, dovrebbe comunque comprendere. Il resto del libro si riferisce a oggetti Template Attribute Language Expression Syntax (TALES) e Script (Python) quindi il lettore dovrebbe prendersi il tempo di acquisire familiarità con loro in questo capitolo. Il lettore dovrebbe avere già una piccola introduzione: nel precedente capitolo abbiamo introdotto le espressioni TALES perché sono usate per generare portlet e action.
| [1] | o page template |
| [2] | o linguaggio di demarcazione per ipertesti |
| [3] | o fogli di stile |
Comprendere il meccanismo di modellazione sottostante
Tuffarsi direttamente dentro il funzionamento dei modelli di pagina (template) di Plone ci porterebbe facilmente in confusione e quindi andremo ad analizzare prima il sottostante meccanismo di modellazione. In un mondo ideale questo dovrebbe essere un qualcosa di cui l'utente non dovrebbe curarsi ma, in pratica, si è osservato che questo è il primo ostacolo in cui le persone incappano quando provano a studiare l'utilizzo di Plone.
Plone è piuttosto unico in quanto tutto in Plone è un oggetto. Se non si è familiari con il concetto di oggetto non ci si preoccupi, non c'è molto da sapere: un oggetto è semplicemente una cosa che incapsula un qualche comportamento. Ogni oggetto ha dei metodi che possono essere richiamati sull'oggetto. Un esempio è un mouse per computer: un mouse per computer può avere metodi come movimento, click e click destro.
In Plone un documento è un particolare tipo di oggetto. Questo significa che un documento non è semplicemente un frammento di testo statico ma bensì un qualcosa di un po' più complicato e più utile. Un documento in Plone ha, per esempio, un metodo description che restituisce la descrizione che l'utente ha aggiunto per il particolare documento. Quando si userà il sistema di modellazione si vedrà più in dettaglio come tutto sia un oggetto. Guardiamo per prima cosa i principi base della pubblicazione di oggetti.
Introduzione alla pubblicazione di oggetti
In Plone si pubblicano oggetti che sono in realtà collocati all'interno di Zope; la maggior parte di essi sono oggetti che sono memorizzati, appunto, nel database degli oggetti. Il concetto è più complicato rispetto all'ambiente Standard Common Gateway Interface (CGI) dove uno script viene eseguito passandogli una serie di variabili relative alla richiesta. Tutto in Plone è un oggetto, tutto in Zope è un oggetto, tutto in Python è un oggetto. Fino ad adesso si è cercato di evitare di utilizzare la parola oggetto utilizzando al suo posto i termini modello di pagina, script e elemento ma tutti questi in realtà sono oggetti, semplicemente oggetti che si comportano in maniera differente.
Quando si richiede un Uniform Resource Locator [4] (URL) a Plone viene invocato un oggetto dell'ambiente. Plone fa questo trasformando l'URL in un path o percorso. Quindi, se l'URL è /Plone/login_form, quello che Plone fa è scomporre questo URL in un path e cercare ognuno di questi oggetti nel database. Plone troverà un oggetto Plone e dentro quello un altro oggetto chiamato login_form. Il percorrere questo percorso è detto attraversamento: essenzialmente Zope risale attraverso questi oggetti e invoca l'ultimo nel path.
Quando Zope chiama l'oggetto login_form, l'oggetto viene eseguito nel suo contesto. Questo termine si incontra spesso in Plone. È banalmente il contesto corrente dell'oggetto che sta per essere eseguito. Nel nostro esempio è /Plone. Il contesto varia molto muovendosi all'interno del sito Plone. Se si fosse richiesto l'URL /Plone/Members/login_form il contesto sarebbe stato /Plone/Members.
Come menzionato il meccanismo di attraversamento è il sistema con cui è possibile accedere agli oggetti in Plone per via programmatica, allo stesso modo che tramite un URL. Questo è simile ad accedere agli elementi di un file system: se si vuole accedere ad una foto nella cartella Miei Documenti in Windows si immette una directory del tipo c:\Documenti e Impostazioni\andrea\Miei Documenti\Fotografia; allo stesso modo per accedere a un oggetto Plone si immetterebbe Members/andrea/Fotografia.jpg. Questo funziona se si ha una serie di cartelle ed oggetti che assomiglia a questo:
Members
|_ andrea
|_ Fotografia.jpg
Nell'esempio con il file system si attraversa il disco fisso del computer cartella per cartella. In Plone succede la stessa cosa, solo che Members e andrea sono oggetti.
Una particolarità è che Zope fa distinzione tra maiuscole e minuscole. Mentre in Windows è possibile scrivere Fotografia.jpg o fotografia.JPG, questo non funziona in Plone: è necessario fornire il nome dell'oggetto con le stesse maiuscole e minuscole dell'ID dell'oggetto. Per questa ragione è raccomandato cercare di mantenere tutti gli URL in caratteri minuscoli in modo da ridurre le possibilità di errore da parte degli utenti.
Plone e Zope hanno aggiunto un elemento chiamato acquisizione a tutto questo sistema di pubblicazione. Il concetto alla base dell'acquisizione è quello di contenimento: gli oggetti sono collocati all'interno di altri oggetti chiamati contenitori. Nell'esempio precedente l'oggetto andrea è un contenitore all'interno del contenitore Members all'interno del sito Plone, un contenitore a sua volta (che in definitiva è all'interno del contenitore di applicazioni Zope).
In un ambiente standard orientato agli oggetti, un oggetto eredita il suo comportamento dall'oggetto padre. In Plone e Zope un oggetto eredita il suo comportamento anche dall'oggetto che lo contiene. Un oggetto attraversa la gerarchia di contenimento per determinare i suoi comportamenti.
Quindi, prendiamo l'esempio dell'accesso a Members/andrea/Fotografia.jpg. Cosa avviene se l'oggetto Fotografia.jpg non esiste nella cartella andrea ma esiste più su nella gerarchia? Bene, l'acquisizione lo troverà per noi. Prendiamo la seguente gerarchia:
Members |_ andrea |_ Fotografia.jpg
In questo caso, se si esegue l'URL, Plone seguirà il path fino a andrea e poi cercherà di trovare Fotografia.jpg, inutilmente dato che non esiste in quella cartella. A questo punto Plone cercherà nella gerarchia di contenimento, che è la cartella Members, dove troverà e restituirà l'oggetto Fotografia.jpg. Il risultato è che l'utente vedrà l'immagine, come al solito.
Tuttavia, se si confronta questo con l'esempio precedente, dove l'immagine era contenuta nella cartella andrea, si trovano alcune differenze fondamentali:
- il contesto è lo stesso, nonostante l'oggetto si trovi in una diversa cartella. Il contesto è dato dalla posizione dalla quale l'oggetto è chiamato.
- il contenitore è diverso: il contenitore di Fotografia.jpg è adesso Members, non andrea.
Quindi, quale è la conclusione di tutto questo? Bene, è possibile mettere un oggetto nella cartella principale del sito Plone e tutti gli oggetti potranno accedervi perché sarà individuato per mezzo dell'acquisizione.
Anche se questo probabilmente ha un senso, l'aquisizione può essere abbastanza complicata, specialmente guardando attraverso la gerarchia del contesto (può succedere). Per approfondire il funzionamento dell'acquisizione si consiglia l'eccellente discussione sull'argomento dello sviluppatore di Zope Jim Fulton.
| [4] | o "indicatore di posizione uniforme di risorse" |
Introduzione alle Template Expressions
Prima di avventurarci nel sistema dei modelli di pagina di Zope è necessario capire TALES. Spesso in un applicazione si ha il bisogno di scrivere espressioni che vengano interpretate dinamicamente. Questi non sono script, piuttosto si tratta di semplici espressioni di una riga (one liners) che possono fare qualcosa di semplice e facile.
Un'espressione è valutata passando ad essa una serie di variabili locali determinate da cosa sta chiamando l'espressione. Il controllo di flusso passa un set di variabili, il sistema dei modelli di pagina Zope Page Template ne forniscono di ulteriori. Per il momento useremo esempi in cui è definito un contesto. Si ricorda che, come detto, il contesto è quello in cui l'oggetto viene eseguito.
Finora abbiamo incontrate alcune espressioni TALES, come ad esempio string:${portal_url}/Software. Tuttavia questo è soltanto un esempio di un'ampia varietà di espressioni. Il principale uso delle espressioni TALES è nei modelli di pagina di Zope, il sistema di generazione dell'HTML di Plone. Nonostante il loro nome possa suggerire che siano adatti solo ai modelli di pagina, molti strumenti in Plone utilizzano questa sintassi per fornire semplici espressioni, come ad esempio le azioni, il controllo di flusso, e la sicurazza. Esistono diverse tipologie di espressioni, le descriveremo una ad una.
Usare le Path Expression
Le Path Expressions sono le espressioni predefinite e le più comunemente utilizzate. Diversamente da tutte le altre espressioni esse non richiedono un prefisso per specificarne il tipo. L'espressione comprende uno o più path. Ogni path è separato dal simbolo di barra verticale (|*). Ogni path è una serie di variabili separate dalla barra obliqua (/). Ecco qualche semplice esempio:
context/message context/cartella/title context/Members/andrea/Fotografia.jpg
Quando l'espressione viene valutata il path viene spezzato in corrispondenza della barra obliqua e quindi a partire dalla parte più a sinistra il path viene attraversato per trovare l'oggetto, il metodo od il valore. Quindi l'oggetto viene posto sullo stack attuale e la valutazione passa al valore successivo. Questa procedura è ripetuta fintanto che non viene raggiunta la fine dell'espressione o un valore corrispondente non viene trovato. Se l'oggetto trovato è un dizionario Python o un mapping object verrà richiamato l'opportuno valore del dizionario. Una funzionalità interessante delle path expressions è che l'unico carattere riservato è / quindi i nomi possono contenere spazi e punteggiatura e continuare ad essere valutati.
Quando la fine dell'espressione è raggiunta l'oggetto viene eseguito (se può essere eseguito). Se si tratta di un oggetto non eseguibile viene restituita la rappresentazione come stringa dell'oggetto. Se in qualsiasi momento si verifica un errore nella ricerca (il più comune è che l'attributo richiesto non esista) la valutazione passa all'espressione alternativa, se ce n'è una. Le espressioni alternative si possono specificare separandole con una barra verticale.
Per esempio:
context/cartellaA/title|context/cartellaB/title
L'esempio precedente produce il titolo di cartellaA o il titolo di cartellaB se la prima non esiste. Questo procedimento è ripetuto per ogni espressione fintanto che non ci sono più espressioni o fino alla prima di esse che viene valutata con successo.
Usare le Not Expression
Una not expression è introdotta dal prefisso not:: e semplicemente inverte la valutazione dell'espressione TALES che segue. Visto che nei modelli di pagina di Zope non esiste un operatore if questo tipo di espressioni possono essere utilizzate per effettuare un test sulla negazione di una condizione.
Per esempio:
not: context/message|nothing
Usare le Nocall Expression
Automaticamente quando una path expression raggiunge l'ultimo elemento del path essa lo esegue, se possibile. Il prefisso nocall: fa si che questo non avvenga. Le nocall expression sono raramente utilizzate in Plone, ma qualche volta sono utili. Per esempio possono essere utilizzate per riferirsi ad un oggetto e non alla sua rappresentazione. Un esempio:
nocall: context/immagine
Usare le String Expression
Le string expression permettono di mischiare testo e variabili all'interno di un espressione. Tutte le string expression sono introdotte dal prefisso string:. Questa è un funzionalità utile e la si vedrà usata abbastanza di frequente. Il testo può contenere qualsiasi cosa permessa all'interno di un attributo, il che essenzialmente include i caratteri alfanumerici e lo spazio. All'interno del testo possono esserci nomi di variabili con aggiunto il prefisso $. Qualche esempio:
string: Questa è una stringa piuttosto lunga string: Questo è il titolo: $title
Nel secondo esempio la variabile $title viene valutata. La variabile può essere una qualsiasi path expression. Se il nome della variabile contiene il simbolo / esso deve essere racchiuso tra parentesi graffe {} per identificare l'inizio e la fine dell'espressione.
Per esempio:
string: Questo è il titolo di una immagine: ${context/unaImmagine/title}.
Per poter utilizzare il simbolo $ bisogna raddoppiarlo, in questo modo:
string: Il prezzo in $$US è ${context/qualcheCosa/cost}.
Usare le Python Expression
Le python expression valutano una riga di codice Python. Tutte le python expression cominciano con il prefisso python: e contengono una riga di codice Python.
Per esempio:
python: 1 + 2
Il codice Python viene valutato utilizzando lo stesso modello di sicurezza utilizzato per gli oggetti di tipo Script (Python), come discusso nel Capitolo 6. Per queste ragioni il codice Python deve essere semplice e limitato a funzionalità di presentazione dei contenuti, come formattazione di stringhe e numeri o valutazione di semplici condizioni.
In aggiunta, quasi tutte le altre espressioni TALES menzionate possono essere inserite nel codice python ed eseguite. La sintassi è la seguente:
- path(string): valuta string come una path expression
- string(string): valuta string come una string expression
- exists(string): valuta string come una string expression
- nocall(string): valuta string come una nocall expression
Per esempio, l'espressione seguente:
python: path('context/Members')
è equivalente a questa:
context/Members
Sono state aggiunte alcune convenienti funzioni per assistere gli sviluppatori. La funzione test accetta tre parametri: una espressione che esprime la condizione da valutare e le alternative per il caso di condizione vera o falsa. La condizione viene valutata e viene restituito l'appropriato valore. Per esempio:
python: test(1 - 1, 0, 1)
La funzione same_type accetta due parametri e controlla che essi siano dello stesso tipo. Per esempio:
python: same_type(qualchecosa, '')
Alcuni sviluppatori scoraggiano l'uso di Python all'interno dei modelli di pagina di Zope perché questa pratica implica l'incorporazione della logica dell'applicazione all'interno dei modelli di presentazione. Spesso, come sviluppatori, per ogni pezzo di codice Python aggiunto, è utile chiedersi se questo pezzo di codice non sia meglio estrarlo ed inserirlo in un oggetto Script (Python) separato. Questo non significa che ogni pezzo di Python debba essere rimosso, semplicemente è bene riflettere prima di aggiungerlo.
Sito web del Manuale: Rispolveriamo le Azioni
Nel Capitolo 4 abbiamo aggiunto una azione che punta alla sezione Software del sito in modo che essa appaia come una scheda del portale. Nelle action si è aggiunta questa string expression: string: ${portal_url}/Software. Ora che abbiamo spiegato il significato della variabile portal_url questa espressione ha un po' più di senso. Questo è l'URL al portale, che può variare se stiamo usando un sistema di virtual hosting. L'espressione utilizza l'acquisizione per ottenere l'oggetto portal_url ed inserire il valore risultante nella stringa. Il risultato è che si ottiene sempre un collegamento assoluto alla cartella Software.
Errori da principianti: mescolare Python e stringhe
I principianti tendono talvolta a mescolare Python e stringhe. Tutte le espressioni sono differenti. In altre parole non è possibile inserire costrutti simili alle path expression all'interno di una Python expression. Per esempio l'espressione python: here/Members + "/danae" non ha significato. L'intera espressione è interpretata come Python quindi Plone proverà a dividere here per Members e incapperà in errori. Questa è invece la circostanza ideale per usare un string expression, che permette di effettuare la sostituzione delle variabili che possono essere anche path expression. Quindi si può usare l'espressione string: ${here/Members}/danae.
Usare il sistema dei modelli di pagina Zope Page Templates
Adesso che abbiamo capito la pubblicazione degli oggetti e le espressioni possiamo veramente addentrarci all'interno del sistema dei modelli di pagina Zope Page Templates. Questo è il sistema che Plone utilizza per generare l'HTML.
Sono disponibili molti sistemi di generazione dell'HTML, alcuni dei più conosciuti sono JavaServer Pages, Active Server Pages, e PHP. Se si utilizzano gli altri sistemi quello dei modelli di pagina di Zope sembra inizialmente bizzarro ma presto si scopre che è un sistema molto potente.
Il modello più semplice è qualcosa che assomiglia al seguente:
<p tal:content="here/messaggio">Questo è il titolo</p>
Se il valore della variabile messaggio si risolve in Buongiorno, mondo! quando il modello viene interpretato viene generato il seguente testo:
<p>Buongiorno, mondo!</p>
Tralasciando per il momento alcuni dettagli analizziamo cosa è successo. È stato scritto un comune paragrafo in HTML ma il contenuto del paragrafo nel sorgente non è quello ottenuto come output. Al marcatore di apertura del paragrafo è stato aggiunto un attributo tal:content e l'espressione here/messaggio è stata specificata come valore dell'attributo. Nell'output il contenuto del paragrafo è stato sostituito con il valore della variabile, in questo caso Buongiorno, mondo!.
Al momento dell'esecuzione il modello viene interpretato e l'attributo tal:content eseguito. Il prefisso tal sta per Template Attribute Language e permette di utilizzare alcuni comandi, incluso il comando content. Con tutti questi comandi, che si descriveranno in seguito, è possibile fare praticamente ogni cosa si desideri ai marcatori HTML. È possibile creare iterazioni, modificare i marcatori, modificare gli attributi, rimuovere marcatori e altro ancora. Prima che il modello venga interpretato il modello stesso è un documento che rispetta lo standard Extensible HTML (XHTML) [5] quindi in un editor verrà visualizzato come un paragrafo con quel testo.
Tutti i modelli di pagina sono XHTML validi. Questo è uno standard per l'HTML che rispetta le specifiche Extensible Markup Language (XML) [6]. Questo significa che esso deve sottostare a queste regole:
- Tutti i marcatori devono essere minuscoli.
- Gli attributi devono sempre essere tra apici. Per esempio <input type="checkbox" checked="1" />.
- Gli elementi vuoti devono essere terminati. Per esempio <br /> e non <br>.
Per definire una pagina come XHTML è necessario fornire una dichiarazione del DOCTYPE e specificare lo spazio dei nomi XML con il marcatore html. Plone utilizza la seguente dichiarazione in cima ad ogni pagina:
<!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">
Per maggiori informazioni su XHTML consultare le specifiche.
| [5] | letteralmente "HTML estensibile" |
| [6] | letteralmente "linguaggio estensibile di demarcazione" |
Un altro sistema di generazione dell'HTML?
Nei primi anni del Web erano i programmatori i creatori dell'HTML ed essi rapidamente misero assieme dei sistemi per generare automaticamente l'HTML in modo da potersi concentrare sul loro vero lavoro. Con questi strumenti, come ad esempio i moduli CGI del Perl, i programmatori poterono scrivere complicati programmi lato server per la gestione dei contenuti.
Tuttavia, presto ognuno cominciò a scrivere contenuti e questi processi dovevano essere semplificati. Questo ha determinato la nascita di molti linguaggi dove il codice è mischiato all'HTML, delimitato da speciali marcatori. I linguaggi interpretavano il codice contenuto tra i marcatori per produrre il risultato desiderato. Come menzionato, alcuni di questi sono Active Server Pages, JavaServer Pages, e persino interi linguaggi di programmazione basati su questo concetto, come PHP. Zope ha seguito questa tendenza creando il Document Template Markup Language o DTML.
Questi sistemi prendevano l'HTML e sparpagliavano in esso marcatori personalizzati come ad esempio <% ... %> o <dtml-... />. Questo sistema divenne popolare perché è di facile comprensione e gli utenti che già conoscono le basi dell'HTML possono ben padroneggiare l'idea di qualche marcatore aggiuntivo. I grafici possono ignorare il contenuto di questi marcatori e lasciare i programmatori ad occuparsi di essi. I programmatori possono modificare le parti di codice senza modificare i contenuti.
Tuttavia questi sistemi presentano i seguenti problemi:
- I modelli HTML possono diventare difficili da gestire man mano che maggiori contenuti sono aggiunti allo script. Le pagine diventano rapidamente enormi e difficili da gestire.
- La logica ed i contenuti non sono nettamente separati. Essi possono essere separati con alcuni di questi sistemi, tuttavia la possibiltà di sparpagliare pezzi di HTML in ogni pezzo di programma è troppo facile. Spesso contenuti, presentazione e logica diventano un grande ed intricato garbuglio.
- Le pagine non possono essere modificate facilmente. Spesso le pagine o i modelli sono forniti con l'annotazione "non toccare questi pezzi..." perché le modifiche potrebbero compromettere il funzionamento del programma. Gli editor What You See Is What You Get [7] (WYSIWYG) possono essere impostati per non modificare alcuni marcatori ma altri possono essere compromessi. In grandi organizzazioni utenti con diversi ruoli devono modificare la medesima pagina.
- Può essere difficile ottenere un risultato predefinito. Prendiamo, ad esempio, una richiesta ad una base di dati che mostri i risultati in una tabella. Come può un grafico vedere come sarà questa tabella senza eseguire il codice?
Per queste ragioni è stato creato il sistema di modelli di pagina Zope. I page template rappresentano un innovativo approccio; invece che fornire un nuovo sistema di escape coding, il codice viene aggiunto agli attributi dei marcatori esistenti. Non solo il sistema dei Zope Page Templates è libero ed open source, esso non richiede nemmeno Zope. Al momento esistono realizzazioni di questo sistema in Python, Perl e Java.
| [7] | letteralmente "quello che vedi è quello che ottieni" |
Introduzione a modelli di pagina e contenuto
Abbiamo imparato che Plone è un sistema di gestione dei contenuti in cui gli utenti aggiungono contenuti al sito Plone attraverso il Web. Gli oggetti che rappresentano i contenuti sono conservati all'interno di Plone e visualizzati al mondo attraverso i modelli di pagina.
Ritornando al precedente esempio dell'accesso a /Members/andrea/Fotografia.jpg discuteremo ora cosa effettivamente succede al contenuto di Plone. Per prima cosa Plone cerca ed esegue l'oggetto Fotografia.jpg; l'oggetto viene eseguito perché non è stato specificato nessun metodo specifico da richiamare. Quando un content type è eseguito un determinato modello viene localizzato ed interpretato. Il contesto per tale modello sarà l'immagine a cui si vuole accedere ed il modello sarà quello associato all'immagine.
Se è stata richiamata sull'immagine una differente azione, ad esempio Members/andrea/Fotografia.jpg/image_edit, l'azione image_edit associata a questo oggetto verrà localizzata e il corrispondente modello verrà restituito. Il Capitolo 11 tratta di come questo avviene in maggiore dettaglio.
In tutti i modelli di pagina, all'interno di Plone, si troveranno riferimenti a here o context. Questo è il contesto del contenuto a cui si sta accedendo. In un modello è possibile quindi riferirsi a context/questo o quello e questo o quello verrà localizzato relativamente al pezzo di contenuto, non al modello. Andiamo quindi a creare il nostro primo modello in Plone.
Creazione del primo modello di pagina
Il metodo standard per creare un modello di pagina è utilizzare la Zope Management Interface (ZMI) [8]. Sfortunatamente la ZMI è scomoda da usare per uno sviluppatore, visto che questo implica modificare il modello tramite una area di testo nel proprio browser Web. L'area di testo fornisce limitate funzionalità rispetto alla maggior parte degli editor; manca di funzionalità quali la numerazione delle righe, l'evidenziazione delle sintassi, e così via. Nel Capitolo 9 si vedrà come utilizzare l'External Editor per modificare i contenuti; questo permette di modificare i contenuti del sito Web in un editor locale come Macromedia Dreamweaver o Emacs. Nel Capitolo 6 si vedrà come far leggere a Plone i modelli di pagina dal disco fisso come file, si potrà quindi utilizzare qualsivoglia strumento per modificarle.
Per creare un modello di pagina, si acceda alla ZMI, si selezioni portal_skins, successivamente si selezioni custom e quindi di si scelga l'opzione Page Template dal menù a tendina come in figura 5-1. Si prema quindi Add e si vedrà la pagina mostrata in figura 5-2.
Si immetta test come ID per il modello di pagina. Si prema dunque il pulsante Add and Edit che porterà alla pagina di amministrazione mostrata in figura 5-3. Si può quindi modificare il modello tramite il Web utilizzando l'area di testo e premere il pulsante Save Changes per memorizzare le modifiche.
Nota
Nelle versioni di Plone precedenti Plone 2 in tutte i modelli di pagina era definita la variabile here, equivalente alla variabile context. Se si trova here in qualsiasi parte di un modello di pagina il suo significato è lo stesso di context. La nuova variabile context è stata aggiunta per maggior chiarezza e per allineare i modellidi pagina agli oggetti Script (Python).
Alla pressione del pulsante Save Changes il modello di pagina viene interpretato. Se è stato commesso qualche errore nel modello lo si vedrà evidenziato in cima alla pagina. La Figura 5-4 mostra un errore: un marcatore h1 non è stato chiuso. (Come precedentemente menzionato i modelii di pagina devono contenere codice XHTML corretto).
Una volta che si è correttamente salvato il modello di pagina, è possibile accedere alla scheda Test per vederlo interpretato. Nella Figura 5-5 si vede come l'intestazione sia stata sostituita dall'ID del modello e come il paragrafo principale adesso includa l'ID del modello di pagina.
La finestra di amministrazione di un modello di pagina ha anche le seguenti importanti funzionalità:
- Title:
- il titolo per il modello, è opzionale. Se si modifica, nel precedente esempio, si nota come nella scheda Test l'HTML risultante sia diverso.
- Content-Type:
- il tipo di contenuto del modello, solitamente text/html.
- Browse HTML source:
- restituisce il modello di pagina non interpretato come testo HTML, così come apparirebbe se il modello venisse aperto in un editor HTML.
- Test:
- mostra il modello di pagina interpretato.
- Expand macros when editing:
- opzione che fa si che il sistema provi ad espandere le macro. Si raccomanda di mantenere questa opzione non selezionata nella maggior parte dei casi. Le macro sono una funzionalità avanzata e verranno discusse nel Capitolo 6.
Adesso che si è creato un modello di pagina, lo modificheremo un po'. Questo dimostrerà gli argomenti esposti sin qui in questo capitolo. Per esempio se si vuole provare a far eseguire al modello di pagina l'operazione 1+2 aggiungeremo al modello la seguente riga:
<p>1+2 = <em tal:content="python: 1+2" /></p>
Quindi accediamo alla scheda Test per verificare se funziona. Si dovrebbe ottenere quanto segue:
1+2 = 3
Per vedere un esempio di attraversamento del percorso (path traversal), mostriamo il logo del sito Plone. È possibile includere il logo del sito Plone aggiungendo un'espressione di questo tipo al modello di pagina:
<p tal:replace="structure context/logo.jpg" />
Questo crea l'HTML appropriato per includere l'immagine e la mostrerà nella pagina.
| [8] | letteralmente "interfaccia di amministrazione di Zope" |
Capire la sintassi di base dei modelli di pagina
Adesso che abbiamo visto come creare un modello di pagina spieghiamo la sua sintassi di base. È possibile dividere la sintassi dei modelli di pagina in poche differenti componenti, che descriveremo nei paragrafi seguenti.
Introduzione alle variabili Built-in
Abbiamo visto la sintassi delle espressioni, ora studiamo le variabili che sono passate ad esse quando il modello di pagina viene interpretato. Quanto segue avviene accedendo all'immagine Fotografia.jpg nella cartella Members/andrea, attraverso l'URL /Members/andrea/Fotografia.jpg/.
- container
- questo è il contenitore in cui il modello di pagina è stato localizzato. Solitamente in Plone si tratta della cartella portal_skins. Si dovrebbe evitare di utilizzare questa variabile perché l'oggetto portal_skins può fare cose inaspettate al significato del contenitore (per esempio potrebbe riferirlo alla cartella andrea).
- context
- questo è il contesto nel quale il modello viene interpretato. In Plone questo è l'oggetto che è correntemente visualizzato, se si sta visualizzando un oggetto del portale (per esempio un riferimento all'oggetto Fotografia.jpg).
- default
- qualche espressione ha dei particolari valori predefiniti, documentati separatamente per ogni espressione. Questa variabile è un puntatore a quel particolare valore.
- here
- equivalente a context.
- loop
- equivalente a repeat.
- modules
questo è il contenitore per i moduli importati. Per esempio modules/strings/atoi è la funzione atoi del modulo Python strings. Include tutti i moduli che è sicuro importare all'interno del sistema dei modelli di pagina di Zope. Per maggiori informazioni vedere il paragrafo Scripting Plone con Python nel Capitolo 6.
- nothing
- equivalente di None in Python.
- options
- opzioni passate al modello di pagina, definite solo quando il modello è richiamato da uno script o attraverso un altro metodo, non attraverso il Web.
- repeat
- l'elemento ripetuto; si veda l'elemento tal:repeat nel paragrafo Introduzione alla sintassi delle espressioni TAL di questo capitolo.
- request
richiesta inviata dal client (tutti i valori della richiesta sono visionabili utilizzando lo script test_context sotto riportato). Tutti i parametri passati attraverso i metodi GET o come POST sono ordinati in un dizionario per un facile accesso. Qualche esempio:
request/HTTP_USER_AGENT # il browser usato dall'utente request/REMOTE_ADDR # l'indirizzo del computer dell'utente request/someMessage # il valore di qualche messaggio, nella # stringa di interrogazione- root:
- l'oggetto principale Zope. Per esempio root/Control_Panel restituisce il pannello di controllo di Zope.
- template:
- il modello correntemente interpretato. Per esempio template/id da l'ID del modello attualmente visualizzato.
- traverse_subpath:
- contiene una lista degli elementi che devono ancora essere attraversati. Questa è una variabile avanzata e si raccomanda di utilizzarla solo una volta compreso il meccanismo di attraversamento ed acquisizione.
- user:
- l'oggetto utente corrente. Per esempio user/getUserName da il nome utente dell'utente corrente.
- CONTEXTS:
- l'elenco di molte di queste variabili.
Nota
Con l'eccezione di CONTEXTS tutte queste variabili possono essere ridefinite a piacimento in un'espressione tal:define. Tuttavia questo può portare confusione in tutti quelli che utilizzeranno il codice e non è quindi raccomandato.
Il modello di pagina test_context mostra tutti valori di queste variabili oltre che alla posizione di alcuni oggetti (vedere il Listato 5-1). Può essere utile per scovare eventuali errori o comprendere meglio il significato delle variabili. Aggiungiamolo come modello di pagina chiamata test_context quindi accediamo alla scheda Test per vedere il risultato.
Listato 5-1. test_context
<html>
<head />
<body>
<h1>Debug information</h1>
<h2>CONTEXTS</h2>
<ul>
<tal:block
tal:repeat="item CONTEXTS">
<li
tal:condition="python: item != 'request'"
tal:define="context CONTEXTS;">
<b tal:content="item" />
<span tal:replace="python: context[item]" />
</li>
</tal:block>
</ul>
<h2>REQUEST</h2>
<p tal:replace="structure request" />
</body>
</html>
Il modello di pagina test_context produce il risultato mostrato in Figura 5-6.
Introduzione alla sintassi delle espressioni TAL
Il Template Attribute Language (TAL) fornisce tutti i pezzi necessari alla creazione di una rappresentazione dinamica. TAL definisce otto istruzioni: attributes, condition, content, define, omit-tag, on-error, repeat and replace.
Siccome i modelli di pagina sono documenti XML validi tutti gli attributi TAL devono essere in lettere minuscole e ogni elemento può aver associato ogni istruzione una solo volta. Negli esempi che seguono si sono inseriti dei ritorni a capo all'interno delle definizioni degli elementi per migliorare la leggibilità del codice; questo non compromette la validità del codice ed è abbastanza comune nei sorgenti di Plone. Tuttavia è opzionale e non è richiesto.
tal:attributes: modificare gli attributi di un elemento
L'istruzione tal:attributes permette di rimpiazzare uno o più attributi di un elemento. Un'istruzione contiene il nome dell'attributo da modificare e, separata da uno spazio, l'espressione che specifica il suo valore. Per esempio:
<a href="#" tal:attributes="href context/absolute_url"> Qui c'è il Link </a>
Questo assegna all'attributo href del collegamento il valore del risultato dell'interpretazione di here/absolute_url. L'attributo href è stato già definito su questo elemento in modo che un grafico, aprendo questa pagina, veda un elemento corretto (anche se il collegamento potrebbe non avere senso fintanto che il modello non viene interpretato). Un esempio di risultato dato della valutazione del modello è il seguente:
<a href="http://plone.org/Members/andy/book">Qui c'è il Link</a>
Dato che ogni elemento può avere più attributi, tal:attributes permette di modificarne uno o più simultaneamente specificando più espressioni. Per modificare più attributi in un sol colpo le espressioni vanno separate con un punto e virgola (;). Se gli attributi o i valori da inserire contengono un punto e virgola esso va quotato inserendone un'altro immediatamente dopo (;;). Per esempio, per modificare entrambi gli attributi href e title dell'elemento procediamo come segue:
<a href="#"
tal:attributes="href context/absolute_url;
title context/title_or_id">Link</a>
Un esempio di risultato ottenuto è il seguente:
<a href="http://plone.org/Members/andy/book" title="Plone Book">Link</a>
Le istruzioni tal:attributes e tal:replace sono mutuamente esclusive in quanto replace elimina l'elemento su cui agisce. Se il sistema dei modelli di pagina di Zope si accorge che su un elemento sono state utilizzate le due istruzioni mostra un messaggio di avvertimento e ignora l'attributo tal:attributes. Se l'espressione indicata per il valore di un attributo restituisce il valore default allora nessuna modifica è apportata. Per esempio:
<a href="#"
tal:attributes="href python:request.get('message', default)">
Link
</a>
In questo esempio si utilizza la funzione get dell'oggetto request. Se la richiesta avanzata alla pagina contiene la variabile message allora il primo valore viene utilizzato, se la variabile message non è presente viene utilizzato il secondo valore, default. Quindi solo specificando il parametro message la modifica ha luogo.
tal:condition: valutare condizioni
L'istruzione tal:condition permette di verificare una condizione prima di intepretarne un elemento. Per esempio:
<p tal:condition="request/message">
C'è un messaggio
</p>
<p tal:condition="not: request/message">
Nessun messaggio
</p>
Il paragrafo con il testo per un messaggio viene visualizzato solo se la variabile request ha un un attributo message ed il suo valore è vero (per esempio: la lunghezza della stringa è maggiore di zero). Avere la possibilità di verificare una condizione è inutile se non può essere verificata la condizione opposta; questo è possibile grazie all'espressione not:. Il prefisso not: inverte l'espressione, così not: request/message è interpretato come vero solo se l'attributo message della variabile request è falso (per esempio: la lunghezza della stringa è zero). In questo caso l'attributo message dell'oggetto request deve comunque esistere.
In TAL sono interpretati come falsi:
- il numero zero
- qualsiasi numero complesso o float che indica zero (per esempio 0.0)
- stringhe di lunghezza nulla (per esempio "")
- una lista o una tupla vuote
- un dizionario vuoto
- il valore None di python
- il valore nothing di TALES
mentre sono interpretati come veri:
- il valore default
- qualsiasi numero diverso da zero
- stringhe di lunghezza non nulla
- stringhe composte di soli spazi (per esempio " ")
- qualsiasi altra cosa
tal:content: aggiungere del testo
L'istruzione tal:content è probabilmente la più usata in un modello di pagina. Questa istruzione è anche una delle più semplici, rimpiazza il contenuto di un elemento con il valore specificato. Per esempio:
<i tal:content="context/title_or_id">Qualche titolo</i>
Il risultato di esempio è il seguente:
<i>Un determinato titolo</i>
Il testo Qualche titolo è rimpiazzato con il valore dell'espressione context/title_or_id. Se il testo da inserire contiene elementi HTML essi verranno quotati; il prefisso structure permette di inserire elementi HTML senza che essi siano quotati. Per esempio:
<i tal:content="structure here/title_or_id">Do not escape HTML</i>
Se l'elemento a cui è applicato l'attributo tal:content contiene altri elementi, tutti essi verranno rimpiazzati. Gli attributi tal:content e tal:replace sono mutuamente esclusivi; non possono essere assegnati entrambi allo stesso elemento, verrà segnalato un errore se si prova a farlo. Se il valore dell'attributo tal:content è default il contenuto dell'elemento non viene modificato.
tal:define: definire variabili
L'istruzione tal:define permette di creare variabili che potranno essere utilizzate all'interno del modello. Per esempio:
<p tal:define="title here/title_or_id">
... <i tal:content="title">Titolo</i> ...
</p>
In questo esempio la variabile title è creata assegnandovi il risultato dell'espressione here/title_or_id; successivamente la variabile title è utilizzata in un'istruzione tal:content. Se non diversamente specificato la variabile è creata solo localmente con visibilità limitata all'elemento corrente. Nel precedente esempio, quindi, solo gli elementi interni al marcatore p possono utilizzare la variabile title. È possibile ridefinire la variabile dovunque all'interno dell'istruzione o utilizzarla in altri elementi quante volte si necessita.
Per creare una variabile utilizzata globalmente è possibile utilizzare il prefisso global. Questo permette di accedere alla variabile da qualsiasi parte del modello, non solamente all'interno dell'elemento che la definisce. Per esempio:
<p tal:define="global title string:Foo bar">
... <i tal:content="title">Titolo</i> ...
</p>
<i tal:content="title">Anche qui abbiamo un titolo</i>
Inoltre Plone incorpora un gran numero di definizioni globali in modo che gli utenti possano usarle semplicemente nei loro script. Siccome ognuna di queste definizioni può essere soggetta a modifiche si raccomanda di utilizzare tali variabili con occulatezza. Queste definizioni mettono a disposizione un gran numero di variabili globali. Per esempio, per ottenere il titolo del sito Plone, è possibile semplicemente usare quanto segue:
<p tal:content="portal_title" />
È possibile trovare queste definizioni nella ZMI selezionando portal_skins, quindi plone_templates ed infine global_defines. Si trova un elenco completo di tutte le definizioni e una spiegazione del loro significato nell'Appendice A.
tal:omit-tag: rimuovere elementi
L'istruzione tal:omit-tag è poco comune. Essa permette di rimuovere un marcatore. Dato che il sistema di modelli di pagina di Zope richiede l'uso di marcatori HTML, pagine complicate possono richiedere spesso l'uso di molti elementi che possono portare all'aggiunta di marcatori non necessari. Utilizzando questa istruzione il marcatore a cui è applicata è rimosso lasciandone solo il contenuto. Per esempio:
<p tal:omit-tag="">Questo è un testo</p>
Il risultato è il seguente:
Questo è un testo
In questo esempio viene visualizzato Questo è un testo mentre il marcatore è stato omesso. Opzionalmente come argomento può essere specificata un'espressione. Se l'espressione viene interpretata come falsa allora l'istruzione tal:omit-tag non ha effetto. Per esempio, questo non fa nulla:
<p tal:omit-tag="nothing">Questo è un testo</p>
Un'alternativa all'istruzione tal:omit-tag è l'uso dello spazio dei nomi tal come illustrato nel paragrafo Consigli utili del Capitolo 6.
tal:on-error: effettuare la gestione degli errori
L'istruzione tal:on-error fornisce un metodo per gestire gli errori. Essa agisce in modo simile all'istruzione tal:content, anch'essa produce la sostituzione del contenuto dell'elemento a cui è applicata, ma è attivata solo quando accade un errore.
Il seguente è un esempio:
<p tal:content="request/message"
tal:on-error="string: Nessun messaggio">Testo messaggio</p>
Se c'è un errore interpretando l'espressione request/message allora l'attributo tal:on-error è attivato. Questo causa il rimpiazzo del contenuto dell'elemento con il testo Nessun messaggio.
Sfortunatamente l'istruzione on-error è piuttosto limitata. Non può distinguere tra differenti errori e permette di specificare una sola istruzione da interpretare. Questa limitazione è voluta per evitare un abuso di questa istruzione. La gestione degli errori deve essere effettuata nella logica dell'applicazione.
Fortunatamente, per tutti gli argomenti delle istruzioni, è possibile fornire un'alternativa alla prima espressione, se essa viene interpretata con qualcosa diverso da vero o falso (in altre parole, se si incorre in un errore). Ogni alternativa è separata da una barra verticale (|), più alternative possono essere fornite per un'istruzione. Se si fa affidamento su variabili definite nella richiesta inoltrata si aggiunga sempre un'alternativa |nothing alla fine per assicurarsi che non venga segnalato un errore di tipo AttributeError.
Per esempio:
<p
tal:content="request/message"
tal:condition="request/message|nothing">
C'è un messaggio
</p>
<p tal:condition="not: request/message|nothing">
Nessun messaggio
</p>
Questo secondo esempio è più prolisso ma preferibile per un paio di ragioni:
- il grafico può vedere sia l'alternativa per la condizione positiva, sia quella per la condizione negativa
- è possibile gestire gli errori in maniera più complessa che semplicemente visualizzando una stringa
tal:repeat: realizzare iterazioni
L'istruzione tal:repeat permette di iterare su oggetti ed è una delle istruzioni più complicate. Un'istruzione contiene il nome della variabile alla quale assegnare l'elemento corrente per ogni iterazione, separata da uno spazio dall'espressione che restituisce i valori su cui iterare.
Un esempio di iterazione:
<table>
<tr tal:repeat="row context/portal_catalog">
<td tal:content="row/Title">Titolo</td>
</tr>
</table>
In questo esempio l'espressione here/portal_catalog restituisce un elenco di risultati. Siccome l'iterazione comincia sull'elemento che specifica la riga della tabella, per ogni elemento nell'elenco dei risultati viene creata una nuova riga nella tabella. Similmente a tal:define ad ogni iterazione un nuovo elemento dell'elenco viene assegnato ad una variabile locale (in questo caso la variabile row). Questo esempio mostra una riga per ogni elemento dell'elenco dei risultati.
È possibile accedere ad alcune utili variabili all'interno dell'istruzione tal:repeat. Queste varibili sono accessibili attraverso l'oggetto repeat, che viene aggiunto al namespace. Per esempio, per accedere all'indice corrente, si utilizza il seguente codice:
<table>
<tr tal:repeat="row context/portal_catalog">
<td tal:content="repeat/row/number">1</td>
<td tal:content="row/Title">Titolo</td>
</tr>
</table>
La lista completa delle variabili accessibili tramite l'oggetto repeat è la seguente:
- index
- l'indice di iterazione, a partire da zero.
- number
- l'indice di iterazione, a partire da uno.
- even
- questa variabile è vera se l'indice di iterazione è pari (ad esempio 0, 2, 4, ...).
- odd
- questa variabile è vera se l'indice di iterazione è dispari (ad esempio 1, 3, 5, ...).
- start
- questa variabile è vera per la prima iterazione.
- end
- questa variabile è vera per l'ultima iterazione.
- lenght
- il numero totale di iterazioni.
- letter
- l'indice di iterazione espresso con una lettera minuscola (ad esempio a-a, aa-az, ba-bz, ... za-zz, aaa-aaz, e così via), a partire da uno.
- Letter
- versione maiuscola della variabile letter
- roman
- l'indice di iterazione espresso in numeri romani (ad esempio i, ii, iii, iv, v, e così via), a partire da uno.
Attraverso l'oggetto repeat sono accessibili anche le variabili first e last, piuttosto insolite e raramente utilizzate. Queste due variabili permettono di memorizzare informazioni sui dati nell'iterazione. Utilizzando i valori che si vogliono memorizzare in un'espressione un valore booleano è restituito.
Questo ne è un esempio:
<ul>
<li tal:repeat="val context/objectValues">
First: <i tal:content="repeat/val/first/meta_type" />,
Last: <i tal:content="repeat/val/last/meta_type" />:
<b tal:content="val/meta_type" />,
<b tal:content="val/title_or_id" />
</li>
</ul>
tal:replace: aggiungere del testo
L'istruzione tag:replace è simile all'istruzione tal:content, con una differenza: rimuove il tag.
Per esempio:
<p tal:replace="context/title_or_id">Some title</p>
Questo visualizza il risultato dell'espressione context/title_or_id ma rimuove il tag p dal risultato. È equivalente al codice che segue:
<p tal:content="here/title_or_id" tal:omit-tag="">Some title</p>
Se l'elemento a cui è applicato l'attributo tal:replace contiene altri elementi allora tutti gli elementi contenuti verrano rimpiazzati. Non è possibile utilizzare l'istruzione tal:replace assieme all'istruzione tal:attributes o all'istruzione tal:content; sono mutuamente esclusive e viene segnalato un errore se si provano ad assegnare allo stesso elemento.
Introduzione all'ordine di esecuzione
L'ordine con cui le istruzioni TAL sono scritte non è l'ordine in cui esse sono interpretate perché esse sono realmente elementi XML (e l'XML non rispetta l'ordine degli attributi). L'ordine in cui le istruzioni sono interpretate è il seguente:
- define
- condition
- repeat
- content
- replace
- attributes
- omit-tag
Non è possibile utilizzare le istruzioni content e replace sullo stesso elemento perché esse sono mutuamente esclusive. Utilizzando l'istruzione attributes sullo stesso elemento insieme replace o omit-tag non ha significato in quanto gli attributi vengono rimossi. L'attributo on-error non è menzionato nell'elenco perché esso è interpretato non appena si incappa nel primo errore in qualsiasi degli elementi elencati.
Esempio: visualizzare informazioni sull'utente
Per illustrare gli argomenti sin qui trattati procediamo adesso con la creazione di un modello di pagina che esegue un semplice compito: mostrare le informazioni che riguardano un utente del sistema.
In questo esempio un'azienda utilizza internamente Plone come intranet. Ogni dipendente è registrato all'interno di Plone e possiede una login; tuttavia non c'è una semplice pagina che mostri i dipendenti o come contattarli. Creeremo una semplice pagina di informazioni sull'utente che mostri l'indirizzo e-mail, l'home page, una foto, e l'ora dell'ultimo login.
Il primo prototipo di questa pagina è facilmente realizzato con TAL, TALES e un po' di conoscenza delle funzionalità di base degli strumenti Content Management Framework (CMF). Sfortunatamente, visto che le Application Management Interfaces (API) per questi strumenti sono abbastanza complesse, parte del codice risulterà più lungo di quanto non dovrebbe essere. A questo livello non ci si preoccupi troppo dell'API; verrano descritte più approfonditamente nel Capitolo 9. Si dia per il momento l'API per scontata e ci si concentri sul TAL.
Per prima cosa creiamo un modello di pagina; selezioniamo portal_skin, quindi custom*, aggiungiamo un modello di pagina dandogli ``ID`` **user_info modificandolo infine come indicato di seguito. Per il listato completo del modello di pagina consultare l'Appendice A. Esaminando il listato completo si vede che esso comincia con i marcatori html e body.
Per comodità si raggruppano le principali definizioni in un marcatore div:
<div
tal:omit-tag=""
tal:define="
userName request/userName|nothing;
userObj python: here.portal_membership.getMemberById(userName);
getPortrait nocall: here/portal_membership/getPersonalPortrait;
getFolder nocall: here/portal_membership/getHomeFolder
">
In questo marcatore div ci sono quattro definizioni: una per ottenere il nome utente ricevuto attraverso la richiesta del client e una per convertire il nome utente in un oggetto di tipo utente. Le ultime due definizioni assicurano di avere dei riferimenti validi ai metodi che restituiscono la foto dell'utente e la sua cartella personale; queste sono nuovamente delle definizioni di convenienza che servono per rendere il codice che segue più semplice. Utilizzare un marcatore div, o qualche altro marcatore simile a questo, che raccolga una serie di definizioni, è una procedura comune all'interno del sistema dei modelli di pagina di Zope. Esso semplicemente mantiene ordine all'interno del codice.
Successivamente inseriamo due semplici condizioni per assicurarci che un utente sia definito:
<p tal:condition="not: userName">
Non è stato selezionato alcun nominativo.
</p>
<p tal:condition="not: userObj">
Il nominativo selezionato non esiste.
</p>
Se nessun nome utente è stato specificato nella richiesta, allora l'espressione request/username|nothing assegna alla variabile userName il valore nothing e quindi il test fallisce. In più se il nome utente non è valido la variabile userObj risulterà None e un messaggio di errore verrà visualizzato per entrambe queste condizioni.
Adesso siamo pronti per visualizzare le informazioni sull'utente:
<table tal:condition="userObj">
<tr>
<td>
<img src=""
tal:replace="structure python: getPortrait(userName)" />
</td>
Siccome è possibile visualizzare le informazioni relative all'utente solo se un utente è stato trovato, ce ne assicuriamo con una semplice condizione applicata alla tabella: tal:condition="userObj". Per visualizzare una foto dell'utente, utilizziamo il metodo getPortrait precedentemente definito. Questa funzione restituisce l'HTML completo necessario a visualizzare l'immagine: per questo il marcatore structure assicura che esso sia correttamente visualizzato. In aggiunta vogliamo visualizzare alcune proprietà come name ed email. Il codice seguente visualizza una di queste, restituendo la cartella home:
<li
tal:define="home python: getFolder(userName)"
tal:condition="home">
<a href=""
tal:attributes="href home/absolute_url"
>Cartella personale</a>
</li>
Per prima cosa si utilizza un define per assegnare l'oggetto che rappresenta la cartella personale dell'utente alla variabile home. In un sito Plone creare una cartella personale per gli utenti è opzionale, quindi è necessario controllare che la cartella esista prima di visualizzare un collegamento ad essa. Fortunatamente, a causa dell'ordine di esecuzione delle istruzioni TAL, la definizione viene interpretata prima della condizione. Con questo si visualizza un collegamento alla cartella utilizzando l'attributo absolute_url dell'oggetto.
Il modello di pagina prosegue con altre righe relative alla visualizzazione di altre utili ed eccitanti proprietà dell'utente. Come la maggior parte delle cose in Plone la chiave risolutiva è trovare le giuste chiamate alle API per poi elaborarne i risultati in base alle necessità.
Infine la pagina termina chiudendo tutti i marcatori che vanno chiusi. Se tutto va bene è possibile consultare la pagina accedendo all'URL http://sitoplone/user_info?userName=[nomeutente] dove [nomeutente] va sostituito con un nome utente che esiste nel sito Plone.
Al momento questo modello di pagina abbastanza limitato. Solo un utente con il ruolo di manager può vedere questa pagina, può visualizzare solo i dati relativi ad un solo utente per volta e le informazioni per l'utente sono piuttosto poche. Nel Capitolo 6 vedremo come espandere questo esempio e come aggiungere la possibilità di riutilizzare qualche componente e la possibilità di tradurre il testo in altre lingue.
Andy McKay: The Definitive Guide to Plone. Apress 2004
It was last updated by lallo on 2005-04-09 07:08 from the cvs source using
svn export http://docit.bice.dyndns.org/Plone/PloneBook2/it LibroPlone.





