- TurboGears 教程
- TurboGears - 首页
- TurboGears - 概述
- TurboGears - 环境
- TurboGears - 第一个程序
- TurboGears - 依赖项
- TurboGears - 服务模板
- TurboGears - HTTP 方法
- Genshi 模板语言
- TurboGears - 包含
- TurboGears - JSON 渲染
- TurboGears - URL 层次结构
- TurboGears - Toscawidgets 表单
- TurboGears - 验证
- TurboGears - 闪存消息
- TurboGears - Cookie 和会话
- TurboGears - 缓存
- TurboGears - SQLAlchemy
- TurboGears - 创建模型
- TurboGears - CRUD 操作
- TurboGears - 数据表格
- TurboGears - 分页
- TurboGears - 管理员访问
- 授权与认证
- TurboGears - 使用 MongoDB
- TurboGears - 脚手架
- TurboGears - 钩子
- TurboGears - 编写扩展
- TurboGears - 可插拔应用程序
- TurboGears - RESTful 应用程序
- TurboGears - 部署
- TurboGears 有用资源
- TurboGears - 快速指南
- TurboGears - 有用资源
- TurboGears - 讨论
TurboGears - Genshi 模板语言
Genshi 是一种基于 XML 的模板语言。它类似于Kid,后者曾是早期版本 TurboGears 的模板引擎。Genshi 和 Kid 都受到其他知名模板语言的启发,例如HSLT、TAL和PHP。
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:when和py: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:choose和py:when指令的使用。HTML 表单将数据发布到 /marks URL。marks()函数重定向标记并将字典对象形式的结果发送到total.html模板。结果 Pass/Fail的条件显示是通过使用py:choose和py:when指令实现的。
输入标记的HTML脚本(marks.html)如下:
<html> <body> <form action = "https://127.0.0.1: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://127.0.0.1::8080/marksform:
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://127.0.0.1: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://127.0.0.1::8080/marksform。
提交上述表单后,浏览器将显示以下输出。
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://127.0.0.1:8080/macro
浏览器将呈现以下输出:
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://127.0.0.1:8080/macro 呈现以下输出
结构操作指令
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>