TurboGears - Genshi Template Language
Genshi è un linguaggio per modelli basato su XML. È simile aKid, che era il motore dei modelli per le versioni precedenti di TurboGears. Genshi e Kid sono ispirati da altri linguaggi di modelli ben noti comeHSLT, TAL e PHP.
Un modello Genshi è costituito da direttive di elaborazione. Queste direttive sono elementi e attributi in un modello. Le direttive Genshi sono definite in uno spazio dei nomihttp://genshi.edgewall.org/. Quindi questo spazio dei nomi deve essere dichiarato nell'elemento radice del modello.
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/"
lang = "en">
...
</html>
La dichiarazione sopra indica che lo spazio dei nomi predefinito è impostato su XHTML e le direttive Genshi hanno il prefisso "py".
Direttive Genshi
Un certo numero di direttive sono definite in Genshi. Il seguente elenco elenca le direttive Genshi:
- py:if
- py:choose
- py:for
- py:def
- py:match
- py:with
- py:replace
- py:content
- py:attrs
- py:strip
Sezioni condizionali
Genshi fornisce due direttive per la riproduzione condizionale del contenuto: py: if e py: choose.
py: se
Il contenuto dell'elemento di questa direttiva verrà visualizzato solo se l'espressione in if clauserestituisce true. Supponendo che i dati nel contesto del modello siano{‘foo’:True, ‘bar’:’Hello’}, la seguente direttiva -
<div>
<b py:if = "foo">${bar}</b>
</div>
risulterà in
Hello
Questo output, tuttavia, non verrebbe visualizzato se ‘foo’ is set to False.
Questa direttiva può essere utilizzata anche come elemento. In questo caso<py:if> deve essere chiuso da corrispondente </py:if>
<div>
<py:if test = "foo">
<b>${bar}</b>
</py:if>
</div>
py: scegli
L'elaborazione condizionale avanzata è possibile con l'uso di py:choose in combinazione con py:when e py:otherwisedirettive. Questa funzione è simile aswitch – case costruire in C/C++.
Espressione in py:choose viene controllata con diversi valori identificati con py:whenle alternative e i contenuti corrispondenti verranno resi. Un'alternativa predefinita può essere fornita sotto forma dipy:otherwise direttiva.
<div py:choose = "foo”>
<span py:when = "0">0</span>
<span py:when = "1">1</span>
<span py:otherwise = "">2</span>
</div>
L'esempio seguente illustra l'uso di py:choose e py:whendirettive. Il modulo HTML invia i dati a / contrassegna l'URL. Ilmarks() funzione reindirizza i contrassegni e i risultati sotto forma di un oggetto dizionario a total.htmlmodello. La visualizzazione condizionale diresult Pass/Fail si ottiene utilizzando py:choose e py:when direttive.
Script HTML per l'inserimento di segni (marks.html) è il seguente:
<html>
<body>
<form action = "http://localhost:8080/marks" method = "post">
<p>Marks in Physics:</p>
<p><input type = "text" name = "phy" /></p>
<p>Marks in Maths:</p>
<p><input type = "text" name = "maths" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
Il codice completo di root.pyè come segue. Ilmarks() il controller sta inviando contrassegni e risultati a total.html modello -
from hello.lib.base import BaseController
from tg import expose, request
class RootController(BaseController):
@expose("hello.templates.marks")
def marksform(self):
return {}
@expose("hello.templates.total")
def marks(self, **kw):
phy = kw['phy']
maths = kw['maths']
ttl = int(phy)+int(maths)
avg = ttl/2
if avg ≥ 50:
mydata = {'phy':phy, 'maths':maths, 'total':ttl, 'result':2}
else:
mydata = {'phy':phy, 'maths':maths, 'total':ttl,'result':1}
return mydata
Il total.html nella cartella dei modelli riceve i dati del dizionario e li analizza nell'output html in modo condizionale come segue:
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/"
lang = "en">
<head>
<title>TurboGears Templating Example</title>
</head>
<body>
<h2>Hello, Welcome to TurboGears!.</h2>
<h3>Marks in Physics: ${phy}.</h3>
<h3>Marks in Maths: ${maths}.</h3>
<h3>Total Marks: ${total}</h3>
<div py:choose = "result">
<span py:when = "1"><h2>Result: Fail</h2></span>
<span py:when = "2"><h2>Result: Pass</h2></span>
</div>
</body>
</html>
Avvia il server (se non è già in esecuzione)
Gearbox server –reload –debug
accedere http://localhost::8080/marksform nel browser -

Il total.html renderà il seguente output -

py: per
Elemento in py: la direttiva for viene ripetuta per ogni elemento in un iterabile, tipicamente un oggetto List Python. Seitems = [1,2,3] è presente in un contesto di modello, può essere ripetuto seguendo py: per la direttiva -
<ul>
<li py:for = "item in items">${item}</li>
</ul>
Verrà eseguito il rendering del seguente output:
1
2
3
L'esempio seguente mostra i dati del modulo HTML renderizzati nel modello total.html utilizzando py: la direttiva può essere utilizzata anche come segue:
<py:for each = "item in items">
<li>${item}</li>
</py:for>
Script per moduli HTML
<html>
<body>
<form action = "http://localhost:8080/loop" method="post">
<p>Marks in Physics:</p>
<p><input type = "text" name = "phy" /></p>
<p>Marks in Chemistry:</p>
<p><input type = "text" name = "che" /></p>
<p>Marks in Maths:</p>
<p><input type = "text" name = "maths" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
Il loop() il controller legge i dati del modulo e li invia a total.template sotto forma di un oggetto elenco.
from hello.lib.base import BaseController
from tg import expose, request
class RootController(BaseController):
@expose("hello.templates.marks")
def marksform(self):
return {}
@expose("hello.templates.temp")
def loop(self, **kw):
phy = kw['phy']
maths = kw['maths']
che = kw['che']
l1 = []
l1.append(phy)
l1.append(che)
l1.append(maths)
return ({'subjects':['physics', 'Chemistry', 'Mathematics'], 'marks':l1})
Il modello temp.html utilizza il ciclo py: for per eseguire il rendering del contenuto dell'oggetto dict sotto forma di tabella.
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/" lang = "en">
<body>
<b>Marks Statement</b>
<table border = '1'>
<thead>
<py:for each = "key in subjects"><th>${key}</th></py:for>
</thead>
<tr>
<py:for each = "key in marks"><td>${key}</td></py:for>
</tr>
</table>
</body>
</html>
Avvia il server (se non è già in esecuzione)
gearbox server –reload –debug
accedere http://localhost::8080/marksform nel browser.

Il seguente output verrà visualizzato nel browser quando viene inviato il modulo sopra.

py: def
Questa direttiva viene utilizzata per creare una macro. Una macro è uno snippet riutilizzabile di codice modello. Proprio come una funzione Python, ha un nome e può opzionalmente avere parametri. L'output di questa macro può essere inserito in qualsiasi punto di un modello.
La direttiva py: def segue la seguente sintassi:
<p py:def = "greeting(name)">
Hello, ${name}!
</p>
Questa macro può essere rappresentata con un valore variabile al parametro "nome".
${greeting('world')}
${greeting('everybody)}
Questa direttiva può essere utilizzata anche con un'altra versione della sintassi come segue:
<py:def function = "greeting(name)">
<p>Hello, ${name}! </p>
</py:def>
Nell'esempio seguente, macro() controller in root.py invia un dict oggetto con due chiavi nome1 e nome2 al modello macro.html.
from hello.lib.base import BaseController
from tg import expose, request
class RootController(BaseController):
@expose('hello.templates.macro')
def macro(self):
return {'name1':'TutorialPoint', 'name2':'TurboGears'}
Questo modello macro.html contiene la definizione di una macro chiamata saluto. Viene utilizzato per generare un messaggio di saluto per i dati ricevuti dal controller.
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/"
lang = "en">
<body>
<h2>py:def example</h2>
<div>
<div py:def = "greeting(name)">
Hello, Welcome to ${name}!
</div>
<b>
${greeting(name1)}
${greeting(name2)}
</b>
</div>
</body>
</html>
Avvia il server utilizzando gearbox
gearbox serve –reload –debug
Richiama il controller macro () inserendo il seguente URL nel browser -
http://localhost:8080/macro
Il seguente output verrà visualizzato nel browser:

py: con
Questa direttiva consente di assegnare espressioni a variabili locali. Queste variabili locali rendono l'espressione all'interno meno prolissa e più efficiente.
Supponendo che x = 50 sia fornito nei dati di contesto per un modello, il seguente sarà il py: con direttiva -
<div>
<span py:with = "y = 50; z = x+y">$x $y $z</span>
</div>
Risulterà nel seguente output:
50 50 100
Una versione alternativa per py: è disponibile anche con direttiva -
<div>
<py:with = "y = 50; z = x+y">$x $y $z</py:with>
</div>
Nell'esempio seguente, il controller macro () restituisce un oggetto dict con chiavi name, phy e maths.
from hello.lib.base import BaseController
from tg import expose, request
class RootController(BaseController):
@expose('hello.templates.macro')
def macro(self):
return {'name':'XYZ', 'phy':60, 'maths':70}
Il modello macro.html aggiunge i valori delle chiavi phy e matematiche utilizzando py: with direttiva.
<html xmlns = "http://www.w3.org/1999/xhtml"
xmlns:py = "http://genshi.edgewall.org/"
lang = "en">
<body>
<h2>py:with example</h2>
<h3>Marks Statement for : ${name}!</h3>
<b>Phy: $phy Maths: $maths
<span py:with = "ttl = phy+maths">Total: $ttl</span>
</b>
</body>
</html>
Il browser visualizzerà il seguente output in risposta all'URL http://localhost:8080/macro

Direttive sulla manipolazione della struttura
Il py:attrs la direttiva aggiunge, modifica o rimuove gli attributi dall'elemento.
<ul>
<li py:attrs = "foo">Bar</li>
</ul>
Se foo = {‘class’:’collapse’} è presente in un contesto di modello, che verrà visualizzato dallo snippet di cui sopra.
<ul>
<li class = "collapse">Bar</li>
</ul>
Il py:content la direttiva sostituisce qualsiasi contenuto annidato con il risultato della valutazione dell'espressione -
<ul>
<li py:content = "bar">Hello</li>
</ul>
Dato bar = 'Bye' nei dati di contesto, questo produrrebbe
<ul>
<li>Bye</li>
</ul>
Il py:replace direttiva sostituisce l'elemento stesso con il risultato della valutazione dell'espressione -
<div>
<span py:replace = "bar">Hello</span>
</div>
Dato bar = 'Bye' nei dati di contesto, produrrebbe
<div>
Bye
</div>