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>