TurboGears - Genshi 模板語言



Genshi 是一種基於 XML 的模板語言。它類似於Kid,後者曾是早期版本 TurboGears 的模板引擎。Genshi 和 Kid 都受到其他知名模板語言的啟發,例如HSLT、TALPHP

Genshi 模板包含處理指令。這些指令是模板中的元素和屬性。Genshi 指令在一個名稱空間中定義 http://genshi.edgewall.org/ 。因此,需要在模板的根元素中宣告此名稱空間。

<html xmlns = "http://www.w3.org/1999/xhtml"
   xmlns:py = "http://genshi.edgewall.org/"
   lang = "en">
...
</html>

上述宣告意味著預設名稱空間設定為 XHTML,而 Genshi 指令具有“py”字首。

Genshi 指令

Genshi 中定義了許多指令。以下列表列出了 Genshi 指令:

  • py:if
  • py:choose
  • py:for
  • py:def
  • py:match
  • py:with
  • py:replace
  • py:content
  • py:attrs
  • py:strip

條件部分

Genshi 提供了兩個指令用於條件渲染內容:py:if 和 py:choose。

py:if

只有當if 子句中的表示式計算結果為 true 時,才會渲染此指令元素的內容。假設模板上下文中的資料為{‘foo’:True, ‘bar’:’Hello’},則以下指令:

<div>
   <b py:if = "foo">${bar}</b>
</div>

將產生以下結果:

Hello

但是,如果‘foo’設定為 False,則不會渲染此輸出。

此指令也可以用作元素。在這種情況下,<py:if>必須由相應的</py:if>關閉。

<div>
   <py:if test = "foo">
      <b>${bar}</b>
   </py:if>
</div>

py:choose

可以使用py:choose結合py:whenpy:otherwise指令實現高階條件處理。此功能類似於C/C++中的switch-case結構。

檢查py:choose指令中的表示式與使用py:when替代項標識的不同值,並將渲染相應的內容。可以以py:otherwise指令的形式提供預設替代項。

<div py:choose = "foo”>
   <span py:when = "0">0</span>
   <span py:when = "1">1</span>
   <span py:otherwise = "">2</span>
</div>

以下示例說明了py:choosepy:when指令的使用。HTML 表單將資料釋出到 /marks URL。marks()函式重定向標記並將字典物件形式的結果傳送到total.html模板。結果 Pass/Fail的條件顯示是透過使用py:choosepy:when指令實現的。

輸入標記的HTML指令碼(marks.html)如下:

<html>
   <body>
      <form action = "https://: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>

root.py的完整程式碼如下。marks()控制器將標記和結果傳送到total.html模板:

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

templates 資料夾中的total.html接收字典資料,並有條件地將其解析為 html 輸出,如下所示:

<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>

啟動伺服器(如果尚未執行)

Gearbox server –reload –debug

在瀏覽器中輸入https://::8080/marksform

Result Window

total.html將呈現以下輸出:

Total Html

py:for

py:for 指令中的元素將針對可迭代物件中的每個專案重複,通常是 Python 列表物件。如果模板上下文中存在items = [1,2,3],則可以透過以下 py:for 指令對其進行迭代:

<ul>
   <li py:for = "item in items">${item}</li>
</ul>

將呈現以下輸出:

1
2
3

以下示例顯示了使用 py:for 指令在 total.html 模板中渲染的 HTML 表單資料,也可以如下使用:

<py:for each = "item in items">
   <li>${item}</li>
</py:for>

HTML 表單指令碼

<html>
   <body>
	
      <form action = "https://: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>

loop()控制器讀取表單資料並將其以列表物件的形式傳送到 total.template。

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})

temp.html 模板使用 py:for 迴圈以表格形式呈現 dict 物件的內容。

<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>

啟動伺服器(如果尚未執行)

gearbox server –reload –debug

在瀏覽器中輸入https://::8080/marksform

Window Result

提交上述表單後,瀏覽器將顯示以下輸出。

Form Output

py:def

此指令用於建立宏。宏是可重用的模板程式碼片段。類似於 Python 函式,它具有名稱,並且可以選擇具有引數。此宏的輸出可以插入到模板中的任何位置。

py:def 指令遵循以下語法:

<p py:def = "greeting(name)">
   Hello, ${name}!
</p>

此宏可以使用變數值渲染到“name”引數。

${greeting('world')}
${greeting('everybody)}

此指令也可以與另一個版本的語法一起使用,如下所示:

<py:def function = "greeting(name)">
   <p>Hello, ${name}! </p>
</py:def>

在以下示例中,root.py中的macro()控制器將包含兩個鍵 name1 和 name2 的dict物件傳送到 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'}

此 macro.html 模板包含名為 greeting 的宏的定義。它用於為從控制器接收的資料生成問候訊息。

<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>

使用 gearbox 啟動伺服器

gearbox serve –reload –debug

透過在瀏覽器中輸入以下 URL 來呼叫 macro() 控制器:

https://:8080/macro

瀏覽器將呈現以下輸出:

Def Example

py:with

此指令允許您將表示式分配給區域性變數。這些區域性變數使表示式內部更簡潔且更高效。

假設模板的上下文資料中給出了 x = 50,則以下將是 py:with 指令:

<div>
   <span py:with = "y = 50; z = x+y">$x $y $z</span>
</div>

它將產生以下輸出:

50 50 100

py:with 指令也有另一種版本:

<div>
   <py:with = "y = 50; z = x+y">$x $y $z</py:with>
</div>

在以下示例中,macro() 控制器返回一個包含 name、phy 和 maths 鍵的 dict 物件。

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}

macro.html 模板使用 py:with 指令新增 phy 和 maths 鍵的值。

<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>

瀏覽器將針對 URL https://:8080/macro 呈現以下輸出

Py:for Example

結構操作指令

py:attrs指令新增、修改或刪除元素的屬性。

<ul>
   <li py:attrs = "foo">Bar</li>
</ul>

如果模板上下文中存在foo = {‘class’:’collapse’},則上述程式碼段將呈現。

<ul>
   <li class = "collapse">Bar</li>
</ul>

py:content指令將任何巢狀內容替換為表示式求值的結果:

<ul>
   <li py:content = "bar">Hello</li>
</ul>

在上下文資料中給定 bar = 'Bye',這將產生

<ul>
   <li>Bye</li>
</ul>

py:replace指令將元素本身替換為表示式求值的結果:

<div>
   <span py:replace = "bar">Hello</span>
</div>

在上下文資料中給定 bar = 'Bye',它將產生

<div>
   Bye
</div>
廣告
© . All rights reserved.