- 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 - 原油操作
- TurboGears - 数据网格
- TurboGears - 分页
- TurboGears - 管理员访问
- 授权与认证
- TurboGears - 使用 MongoDB
- TurboGears - 脚手架
- TurboGears - 挂钩
- TurboGears - 编写扩展
- TurboGears - 可插拔应用
- TurboGears - 安静的应用程序
- TurboGears - 部署
- TurboGears 有用资源
- TurboGears - 快速指南
- TurboGears - 有用的资源
- TurboGears - 讨论
涡轮齿轮 - 快速指南
TurboGears - 概述
什么是网络框架?
Web 应用程序框架或简称 Web 框架代表库和模块的集合,它使 Web 应用程序开发人员能够编写应用程序,而不必担心协议、线程管理等底层细节。
什么是涡轮齿轮?
TurboGears 是一个用 Python 编写的 Web 应用程序框架。TurboGears 最初由 Kevin Dangoor 于 2005 年创建,其最新版本 TurboGears(版本 2.3.7)由 Mark Ramm 和 Florent Aide 领导的一组开发人员管理。
TurboGears 遵循模型-视图-控制器范例,就像大多数现代 Web 框架(如 Rails、Django、Struts 等)一样。
模型视图控制器
MVC 是一种用于开发 Web 应用程序的软件设计模式。模型视图控制器模式由三部分组成 -
模型- 模式的最低级别负责维护数据。
视图- 负责向用户显示全部或部分数据。
控制器- 控制模型和视图之间交互的软件代码。
MVC 很受欢迎,因为它将应用程序逻辑与用户界面层隔离并支持关注点分离。在这里,控制器接收应用程序的所有请求,然后与模型一起准备视图所需的任何数据。然后,视图使用控制器准备的数据来生成最终的可呈现的响应。MVC 抽象可以用图形表示如下 -
该模型
模型负责管理应用程序的数据。它响应来自视图的请求,还响应来自控制器的指令来更新自身。
风景
以特定格式呈现数据,由控制器决定呈现数据而触发。它们是基于脚本的模板系统,非常容易与 AJAX 技术集成。
控制器
控制器负责响应用户输入并在数据模型对象上执行交互。控制器接收输入,验证输入,然后执行修改数据模型状态的业务操作。
TurboGears 构建在许多库和工具之上。这些工具在不同版本的 TurboGears 之间发生了变化。下面列出了当前版本(2.3.7 版)的组件。
SQL炼金术
它是一个开源 SQL 工具包,为 Python 代码提供对象关系映射 (ORM)。
源氏
该模板引擎用于构建 TG 应用程序的前端。Web 模板系统将模板与特定数据源结合起来以呈现动态网页。
托斯卡小部件
它是一个小部件库,用于使用服务器端控件生成 HTML 表单。Tosca 还充当连接 JavaScript 小部件和工具包的中间件。
变速箱
它提供了一组命令来管理项目和服务器 TurboGears 应用程序。TurboGears 应用程序可以部署在任何符合 WSGI 的 Web 服务器上。
Web 服务器网关接口 (WSGI) 已被采用作为 Python Web 应用程序开发的标准。WSGI 是 Web 服务器和 Web 应用程序之间的通用接口规范。wsgiref 包是 WSGI 的参考实现。它用于向 Web TurboGears Web 框架添加 WSGI 支持。该包中的 simple_server 模块实现了一个为 WSGI 应用程序提供服务的简单 HTTP 服务器。我们将使用它来测试在本教程中开发的应用程序。
TurboGears - 环境
先决条件
Python 2.6 或更高版本。TurboGears 的早期版本不兼容 Python 3.X。最新版本声称在 Python 3.X 上运行良好。不过TurboGears的官方文档仍然基于Python 2.7环境。
以下命令安装 virtualenv -
pip install virtualenv
该命令需要管理员权限。在 Linux/Mac OS 上,在 pip 之前添加sudo。如果您使用的是 Windows,请以管理员身份登录。在 Ubuntu 上,virtualenv 可以使用其包管理器进行安装。
Sudo apt-get install virtualenv
安装后,将在文件夹中创建新的虚拟环境。
mkdir newproj cd newproj virtualenv venv
激活相应的环境,在Linux/OS X上
venv/bin/activate
在Windows上
venv\scripts\activate
我们现在已准备好在此环境中安装 TurboGears 。TurboGears 的最小安装是通过以下命令完成的 -
pip install TurboGears2
上述命令可以直接运行,无需虚拟环境进行系统范围的安装。
要安装 TurboGears 以及开发工具,请使用以下命令 -
pip install tg.devtools
TurboGears - 第一个程序
TurboGears 具有最小模式,可以快速创建单个文件应用程序。可以使用最少的依赖集快速构建简单的示例和服务。
TG应用程序中的应用程序类继承自TGController类。此类中的方法可供tg模块中的@expose装饰器访问。在我们的第一个应用程序中,index()方法被映射为我们应用程序的根。TGController 类还需要从tg模块导入。
from tg import expose, TGController class MyController(TGController): @expose() def index(self): return 'Hello World turbogears'
接下来,设置应用程序的配置并声明应用程序对象。这里的AppConfig类构造函数采用两个参数 - 设置为 true 的最小属性和控制器类。
config = AppConfig(minimal = True, root_controller = RootController()) application = config.make_wsgi_app()
这里的make_wsgi_app ()函数构造应用程序对象。
为了服务这个应用程序,我们现在需要启动 HTTP 服务器。如前所述,我们将使用wsgiref包中的simple_server模块来设置和启动它。该模块具有make_server()方法,该方法需要端口号和应用程序对象作为参数。
from wsgiref.simple_server import make_server server = make_server('', 8080, application) server.serve_forever()
这意味着我们的应用程序将在本地主机的端口号 8080 上提供服务。
以下是我们第一个 TurboGears 应用程序的完整代码 -
应用程序.py
from wsgiref.simple_server import make_server from tg import expose, TGController, AppConfig class MyController(TGController): @expose() def index(self): return 'Hello World TurboGears' config = AppConfig(minimal = True, root_controller = MyController()) application = config.make_wsgi_app() print "Serving on port 8080..." server = make_server('', 8080, application) server.serve_forever()
从 Python shell 运行上述脚本。
Python app.py
在浏览器地址栏中输入http://localhost:8080以查看“Hello World TurboGears”消息。
TurboGears 的 tg.devtools包含Gearbox。它是一组命令,对于管理更复杂的 TG 项目很有用。可以通过以下 Gearbox 命令快速创建全栈项目 -
gearbox quickstart HelloWorld
这将创建一个名为HelloWorld的项目。
TurboGears - 依赖关系
TurboGears 项目包含以下目录 -
Config - 项目设置和配置所依赖的地方
控制器- 所有项目控制器,Web应用程序的逻辑
i018n - 支持的语言的翻译文件
Lib - 实用的 python 函数和类
模型- 数据库模型
公共静态文件- CSS、JavaScript 和图像
模板- 我们的控制器公开的模板。
测试- 完成的一组测试。
Websetup - 在应用程序设置时执行的功能。
如何安装项目
现在需要安装该项目。项目的基目录中已提供setup.py 。执行此脚本时会安装项目依赖项。
Python setup.py develop
默认情况下,在项目设置时安装以下依赖项 -
- 烧杯
- 源氏
- Zope.sqlalchemy
- sqlalchemy
- 蒸馏器
- 世界卫生组织
- tw2.forms
- tgext.admin ≥ 0.6.1
- 网页助手2
- 通天塔
安装后,通过在 shell 中发出以下命令开始在开发服务器上提供项目服务 -
Gearbox serve –reload –debug
按照上述命令来提供预构建的示例项目。在浏览器中打开http://localhost:8080。这个现成的示例应用程序简要介绍了 TurboGears 框架本身。
在此 Hello 项目中,默认控制器在controllers 目录中创建为Hello/hello/controllers.root.py。让我们使用以下代码修改 root.py -
from hello.lib.base import BaseController from tg import expose, flash class RootController(BaseController): movie = MovieController() @expose() def index(self): return "<h1>Hello World</h1>" @expose() def _default(self, *args, **kw): return "This page is not ready"
一旦基本的工作应用程序准备就绪,就可以在控制器类中添加更多视图。在上面的Mycontroller类中,添加了一个新方法sayHello() 。@expose ()装饰器将/sayHello URL 附加到它。此函数旨在接受 URL 中的名称作为参数。
通过“gearboxserve”命令启动服务器后,http://localhost:8080。即使输入以下 URL,Hello World 消息也会显示在浏览器中 -
http://本地主机:8080/
http://localhost:8080/index
所有这些 URL 都映射到RootController.index()方法。此类还具有_default()方法,只要 URL 未映射到任何特定函数,就会调用该方法。对 URL 的响应通过 @expose() 装饰器映射到函数。
可以从 URL 向公开的函数发送参数。以下函数从 URL 读取名称参数。
@expose() def sayHello(self, name): return '<h3>Hello %s</h3>' %name
以下输出将在浏览器中显示为对 URL 的响应 - http://localhost:8080/?name=MVL
Hello MVL
TurboGears 自动将 URL 参数映射到函数参数。我们的RootController类继承自BaseController。这在应用程序的lib 文件夹中定义为base.py。
其代码如下 -
from tg import TGController, tmpl_context from tg import request __all__ = ['BaseController'] def __call__(self, environ, context): tmpl_context.identity = request.identity return TGController.__call__(self, environ, context)
TGController.__call__分派请求路由到的控制器方法。
TurboGears - 服务模板
事件虽然可以将 HTML 内容返回到浏览器,但对于更高级的输出,始终首选使用模板引擎。在变速箱“快速启动”的全栈项目中,Genshi 被启用为默认模板渲染器。然而,在最小的应用程序中,需要安装并启用 Genshi(或任何其他模板引擎,例如 jinja)。Genshi 模板引擎允许用纯 xhtml 编写模板并验证它们以在编译时检测问题并防止提供损坏的页面。
模板通过使用点符号来引用。在我们的Hello项目中,提供了一个templates目录来存储模板网页。因此,sample.html将被称为hello.templates.sample(未提及扩展名)。TurboGears 通过公开装饰器渲染此模板,并通过tg.render_template()函数将控制器方法链接到它。
公开的控制器函数返回一个Python字典对象。该字典对象又被传递到链接的模板。模板中的占位符由字典值填充。
首先,让我们用纯 html 脚本显示一个网页。公开的控制器返回一个空字典对象,因为我们不打算发送任何要在 HTML 脚本内解析的数据。
如何创建示例 HTML
下面给出了我们的sample.html 。确保它存储在项目的 templates 目录中。
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, Welcome to TurboGears!.</h2> </body> </html>
在root.py中添加sample()函数并通过它公开sample.html。
@expose("hello.templates.sample") def sample(self): return {}
启动Web服务器后,输入URL http://localhost:8080/sample,浏览器中将显示以下结果。
如上所述,字典对象作为参数集合发送到 Genshi 模板。该模板包含“占位符”,这些占位符动态地填充从控制器接收的参数。
让我们更改Sample()函数以将字典对象发送到示例模板。
@expose("hello.templates.sample") def sample(self,name): mydata = {'person':name} return mydata
在模板文件夹( templates\sample.html )中创建sample.html
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h2>Hello, my name is ${person}!.</h2> </body> </html>
在上面的 HTML 代码中,${person}是占位符。在浏览器中输入http://localhost:8080/sample?name=MVL作为 URL。该 URL 映射到根控制器中的sample()方法。它返回一个字典对象。这是通过模板目录中的链接模板页面 example.html 选择的。然后,网页中的 ${person} 被 MVL 替换。
还可以在控制器函数中访问 HTML 表单数据。HTML 表单用于发送表单数据。
TurboGears - HTTP 方法
Http 协议是万维网数据通信的基础。该协议定义了从指定 URL 检索数据的不同方法。下表总结了不同的 http 方法 -
先生。 | HTTP 方法和描述 |
---|---|
1 | 得到 以未加密的形式将数据发送到服务器。最常用的方法。 |
2 | 头 与 GET 相同,但没有响应正文 |
3 | 邮政 用于将 HTML 表单数据发送到服务器。服务器不会缓存通过 POST 方法接收的数据。 |
4 | 放 将目标资源的所有当前表示替换为上传的内容。 |
5 | 删除 删除 URL 给出的目标资源的所有当前表示 |
创建 HTML 表单
让我们创建一个 HTML 表单并将表单数据发送到 URL。将以下脚本保存为login.html
<html> <body> <form action = "http://localhost:8080/login" method = "get"> <p>Enter Name:</p> <p><input type = "text" name = "nm" /></p> <p><input type = "submit" value = "submit" /></p> </form> </body> </html>
在此表单中输入的数据将提交至“/login”URL。现在创建一个控制器函数loginpage()并将上面的 html 页面暴露给它。
@expose("hello.templates.login") def loginpage(self): return {}
为了接收表单数据,请提供一个login()控制器,该控制器以表单属性作为其参数。这里“nm”是登录表单中文本输入字段的名称,同样用作login()函数的参数。
@expose("hello.templates.sample") def login(self, nm): name = nm return {'person':name}
可以看出,从登录表单收到的数据被发送到sample.html 模板(之前使用过)。它由Genshi 模板引擎解析以生成以下输出 -
邮寄方式
当 HTML 表单使用 POST 方法将数据发送到 action 属性中的 URL 时,表单数据不会在 URL 中公开。控制器函数在dict参数中接收编码数据。下面的** kw参数是保存数据的字典对象。
HTML 表单包含两个输入文本字段。
<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>
marks ()控制器接收表单数据并将其发送到sample.html模板。root.py的代码如下 -
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.sample") def marks(self, **kw): phy = kw['phy'] maths = kw['maths'] ttl = int(phy)+int(maths) mydata = {'phy':phy, 'maths':maths, 'total':ttl} return mydata
最后,sample.html 模板如下 -
<html> <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> </body> </html>
启动服务器(如果尚未运行)
Gearbox server –reload –debug
在浏览器中输入http://localhost::8080/marksform
Sample.html将呈现以下输出-
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 指令 -
- py:如果
- py:选择
- py:对于
- py:定义
- py:匹配
- py:与
- py:替换
- py:内容
- py:属性
- py:条带
条件部分
Genshi 提供了两个用于条件渲染内容的指令 - py:if 和 py:choose。
py:如果
仅当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:选择
通过将py:choose与py:when和py:otherwise指令结合使用,可以实现高级条件处理。这个特性类似于C/C++中的switch-case构造。
使用py:choose指令中的不同值来检查表达式:何时将呈现替代项和相应的内容。可以以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模板。结果通过/失败的条件显示是通过使用py:choose和py:when指令实现的。
输入标记的 HTML 脚本 ( marks.html ) 如下 -
<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>
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
在浏览器中输入http://localhost::8080/marksform -
Total.html将呈现以下输出-
py:对于
py:for 指令中的元素对于可迭代对象(通常是 Python List 对象)中的每个项目重复。如果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 = "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>
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
在浏览器中输入http://localhost::8080/marksform 。
提交上述表单后,浏览器中将显示以下输出。
py:定义
该指令用于创建宏。宏是模板代码的可重用片段。与 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 serve –reload –debug
通过在浏览器中输入以下 URL 来调用 Macro() 控制器 -
http://localhost:8080/宏
以下输出将在浏览器中呈现 -
py:与
该指令允许您将表达式分配给局部变量。这些局部变量使内部的表达式更简洁、更高效。
假设在模板的上下文数据中给出 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 http://localhost: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>
TurboGears - 包括
可以通过在当前文档中使用包含标签来包含另一个 XML 文档(尤其是 HTML 文档)的内容。为了启用此类包含,必须在 HTML 文档的根元素中声明 XInclude 命名空间。
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude >
上面的声明指定 include 指令包含“xi”前缀。要在当前文档中添加另一个 html 页面的内容,请使用 xi:include 指令,如下所示 -
<xi:include href = "somepage.html" />
在以下示例中,root.py 包含 include() 控制器,该控制器公开 include.html。
from hello.lib.base import BaseController from tg import expose, request class RootController(BaseController): @expose('hello.templates.include') def include(self): return {}
标题和页脚 HTML
在include.html中,声明了include命名空间,并添加了heading.html和footer.html的内容。这是 templates\include.html 的 HTML 脚本 -
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears Templating Example</title> </head> <body> <xi:include href = "heading.html" /> <h2>main content </h2> <xi:include href = "footer.html" /> </body> </html>
这是 templates\heading.html 代码 -
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h1>This is page Header</h1> </body> </html>
以下是templates\footer.html
<html> <head> <title>TurboGears Templating Example</title> </head> <body> <h3>This is page footer</h3> </body> </html>
使用变速箱开始开发,在浏览器中输入http://localhost:8080/include 。呈现的输出如下所示 -
这样就可以实现视图的模块化构造。如果 xi:include 指令中提到的资源不可用,则会引发错误。在这种情况下,可以使用 xi:fallback 加载替代资源。
<xi:include href = “main.html”> <xi:fallback href = ”default.html”/> </xi.include>
内容的包含可以动态化为可以包含表达式的 href 属性。
在 root.py 中添加以下控制器。
@expose('hello.templates.ref-include') def refinclude(self): return {'pages':['heading','main','footer']}
将以下代码另存为 templates 文件夹中的 ref-include.html。
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears Templating Example</title> </head> <body> <xi:include href = "${name}.html" py:for = "name in pages" /> </body> </html>
在启动服务器之前,请确保模板文件夹中有 header.html、main.html 和 footer.html。在浏览器中输入http://localhost:8082/refinclude得到如下输出
TurboGears - JSON 渲染
@expose ()装饰器默认渲染 html 内容。但是,可以将其设置为json 内容类型。TurboGears 通过tg.jsonify.JSONEncoder ( **kwargs )类支持 json 渲染。要渲染 json 数据,只需将 json 作为内容类型传递以公开装饰器。
@expose('json') def jsondata(self, **kwargs): return dict(hello = 'World')
如果在浏览器中输入“/jsondata”URL,它将通过显示进行响应 -
{"hello": "World"}
jsonp 渲染
jsonp 代表带填充的 json。它的工作方式与 json 输出类似,不同之处在于它提供了一个应用程序/javascript 响应,并调用了一个 javascript 函数,该函数将控制器返回的所有值作为函数参数提供。
要启用 jsonp 渲染,您必须首先将其附加到应用程序内所需引擎的列表中 – config/app_cfg.py -
base_config.renderers.append('jsonp')
按如下方式编写您的暴露装饰器 -
@expose('json') @expose('jsonp') def jsonpdata (self, **kwargs): return dict(hello = 'World')
访问 /jsonpdata?callback = callme 时,您应该看到 -
callme({"hello": "World"});
TurboGears - URL 层次结构
有时,Web 应用程序可能需要具有多个级别的 URL 结构。TurboGears 可以遍历对象层次结构以找到可以处理您的请求的适当方法。
带有变速箱的“快速启动”项目在项目的 lib 文件夹中有一个 BaseController 类。它以“Hello/hello/lib/base.py”形式提供。它作为所有子控制器的基类。为了在应用程序中添加一个子级别的URL,设计一个从BaseController派生的名为BlogController的子类。
该 BlogController 有两个控制器函数:index() 和 post()。两者都旨在公开一个模板:blog.html 和 post.html。
注意- 这些模板放在子文件夹中 - templates/blog
class BlogController(BaseController): @expose('hello.templates.blog.blog') def index(self): return {} @expose('hello.templates.blog.post') def post(self): from datetime import date now = date.today().strftime("%d-%m-%y") return {'date':now}
现在在 RootController 类(在 root.py 中)中声明此类的一个对象,如下所示 -
class RootController(BaseController): blog = BlogController()
顶级 URL 的其他控制器函数将像之前一样存在于此类中。
当输入URL http://localhost:8080/blog/时,它将被映射到 BlogController 类中的 index() 控制器函数。同样,http://localhost:8080/blog/post将调用 post() 函数。
blog.html 和 post.html 的代码如下 -
Blog.html <html> <body> <h2>My Blog</h2> </body> </html> post.html <html> <body> <h2>My new post dated $date</h2> </body> </html>
当输入URL http://localhost:8080/blog/时,它将产生以下输出 -
当输入URL http://localhost:8080/blog/post时,它将产生以下输出 -
TurboGears – ToscaWidgets 表格
任何 Web 应用程序最重要的方面之一就是为用户呈现用户界面。HTML 提供了一个 <form> 标签,用于设计界面。可以适当使用文本输入、单选、选择等表单元素。用户输入的数据通过 GET 或 POST 方法以 Http 请求消息的形式提交到服务器端脚本。
服务器端脚本必须从 http 请求数据重新创建表单元素。因此,在这种情况下,表单元素必须定义两次——一次在 HTML 中,另一次在服务器端脚本中。
使用 HTML 表单的另一个缺点是很难(如果不是不可能的话)动态呈现表单元素。HTML 本身不提供验证用户输入的方法。
托斯卡小部件2
TurboGears 依赖于 ToscaWidgets2,一个灵活的表单渲染和验证库。使用 ToscaWidgets,我们可以在 Python 脚本中定义表单字段并使用 HTML 模板呈现它们。还可以对 tw2 字段应用验证。
ToscaWidgets 库是许多模块的集合。下面列出了一些重要的模块 -
tw2.core - 它提供核心功能。此模块中的小部件并不可供最终用户使用。
tw2.forms - 这是一个基本的表单库。它包含字段、字段集和表单的小部件。
tw2.dynforms - 这包含动态表单功能。
tw2.sqla - 这是 SQLAlchemy 数据库的接口。
tw2.forms
它包含一个 Form 类,该类充当自定义表单的基础。有一个 TableForm 类在呈现两列表中的字段时非常有用。ListForm 在无序列表中显示其字段。
先生。 | 字段和描述 |
---|---|
1 | 文本域 单行文本输入字段 |
2 | 文本区 多行文本输入字段 |
3 | 复选框 呈现一个带有标签的可检查矩形框 |
4 | 复选框列表 多选组 pf 复选框 |
5 | 单选按钮 用于选择/取消选择的切换按钮 |
6 | 单选按钮列表 一组互斥的单选按钮 |
7 | 密码字段 与 Textfield 类似,但不显示输入键 |
8 | 日历日期选择器 让用户选择日期 |
9 | 提交按钮 提交表单的按钮 |
10 | 图像按钮 顶部有图像的可点击按钮 |
11 | 单选字段 允许从列表中选择单个项目 |
12 | 多重选择字段 允许从列表中选择多个项目 |
13 | 文件字段 上传文件的字段 |
14 | 电子邮件字段 电子邮件输入字段 |
15 | URL字段 用于输入 URL 的输入字段 |
16 | 数字字段 数字旋转盒 |
17 号 | 范围场 数字滑块 |
在以下示例中,构建了使用其中一些小部件的表单。虽然大多数这些小部件是在 tw2.forms 中定义的,但 CalendarDateField 是在 tw2.Dynforms 模块中定义的。因此,这两个模块以及 tw2.core 都是在开始时导入的 -
import tw2.core as twc import tw2.forms as twf import tw2.dynforms as twd
ToscaWidgets 表单是从tw2.forms.form基类派生的类。所需的小部件放置在布局对象内。在这个例子中,使用了TableLayout 。小部件呈现在两列表格中。第一列显示标题,第二列显示输入或选择字段。
使用以下构造函数创建 TextField 对象 -
twf.TextField(size, value = None)
如果没有提及,TextField 对象采用默认大小并且最初为空白。在声明TextArea对象时,可以提及行数和列数。
twf.TextArea("",rows = 5, cols = 30)
NumberField 对象是一个只能接受数字的 TextField。右边框上生成向上和向下箭头,以增加或减少其中的数字。初始值也可以指定为构造函数中的参数。
twf.NumberField(value)
在 CalendarDatePicker 框的右侧,显示一个日历按钮。按下时会弹出日期选择器。用户可以在框中手动键入日期或从日期选择器中进行选择。
twd.CalendarDatePicker()
EmailField 对象呈现一个 TextField,但其中的文本必须是电子邮件格式。
EmailID = twf.EmailField()
下面的表单也有一个RadioButtonList。此类的构造函数包含一个 List 对象作为 options 参数的值。将呈现每个选项的单选按钮。默认选择是用 value 参数指定的。
twf.RadioButtonList(options = ["option1","option2"],value = option1)
CheckBoxList 呈现列表中每个选项的复选框。
twf.CheckBoxList(options = [option1, option2, option3])
下拉列表在此 ToscaWidgets 库中称为 SingleSelectfield。List 对象中与选项参数对应的项目形成下拉列表。可见标题设置为prompt_text 参数的值。
twf.SingleSelectField(prompt_text = 'text', options=['item1', 'item2', 'item3'])
默认情况下,表单显示一个“提交”按钮,其标题为“保存”。为了显示另一个标题,请创建一个 SubmitButton 对象并将其指定为 value 参数。
twf.SubmitButton(value = 'Submit')
表单被提交到一个 URL,该 URL 被指定为表单的操作参数值。默认情况下,表单数据通过http POST方式提交。
action = 'URL'
在下面的代码中,使用上面解释的小部件设计了一个名为AdmissionForm的表单。在 root.py 中的 RootController 类之前添加此代码。
class AdmissionForm(twf.Form): class child(twf.TableLayout): NameOfStudent = twf.TextField(size = 20) AddressForCorrespondance = twf.TextArea("", rows = 5, cols = 30) PINCODE = twf.NumberField(value = 431602) DateOfBirth = twd.CalendarDatePicker() EmailID = twf.EmailField() Gender = twf.RadioButtonList(options = ["Male","Female"],value = 'Male') Subjects = twf.CheckBoxList(options = ['TurboGears', 'Flask', 'Django', 'Pyramid']) MediumOfInstruction = twf.SingleSelectField(prompt_text = 'choose', options = ['English', 'Hindi', 'Marathi', 'Telugu']) action = '/save_form' submit = twf.SubmitButton(value ='Submit')
现在将此代码保存为模板目录中的twform.html -
<!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" lang = "en"> <head> <title>TurboGears Form Example</title> </head> <body> <div id = "tw form"> ${form.display(value = dict(title = 'default title'))} </div> </body> </html>
在 RootController 类(在 root.py 中)中,添加以下控制器函数 -
@expose('hello.templates.twform') def twform(self, *args, **kw): return dict(page = 'twform', form = MovieForm)
在AdmissionForm类中,我们规定/save_form作为操作URL。因此在 RootController 中添加save_form()函数。
@expose() def save_movie(self, **kw): return str(kw)
确保服务器正在运行(使用变速箱服务)。在浏览器中输入 http://localhost:8080/twform 。
按提交按钮会将这些数据发布到save_form() URL,该 URL 将以字典对象的形式显示表单数据。
{ 'EmailID': u'lathkar@yahoo.com', 'NameOfStudent': u'Malhar Lathkar', 'Gender': u'Male', 'PINCODE': u'431602', 'DateOfBirth': u'2015-12-29', 'Subjects': [u'TurboGears', u'Flask', u'Django'], 'MediumOfInstruction': u'', 'AddressForCorrespondance': u'Shivaji Nagar\r\nNanded\r\nMaharashtra' }
TurboGears – 验证
一个好的表单小部件库应该具有输入验证功能。例如,应强制用户在必填字段中输入数据,或验证电子邮件字段是否包含有效的电子邮件,而无需诉诸任何其他编程手段(如 JavaScript 函数)进行验证。
ToscaWidgets 表单库的早期版本过去依赖 FormEncode 模块来提供验证支持。ToscaWidgets2 现在在 tw2.core 模块中提供了内置验证支持。然而,仍然可以使用 FormEncode 验证技术。
为了对 ToscaWidgets 表单进行验证,使用了 @validate 装饰器。
@validate(form, error_handler, validators)
“ form ”是要验证的 ToscaWidgets 表单对象。
“错误处理程序”是用于处理表单错误的控制器方法。
“验证器”是包含 FormEncode 验证器的字典对象。
验证器的类型
tw2.core 模块包含一个验证器类,其他验证器都继承自该类。还可以基于它设计自定义验证器。一些重要的验证器如下所述 -
LengthValidator - 检查值是否具有规定的长度。最小和最大限制由 min 和 max 参数定义。长度低于和高于最小值和最大值的自定义消息可以指定为“tooshort”和“toolong”参数。
tw2.core.LengthValidator(min = minval, max = maxval, msgs = { 'tooshort': (‘message for short length’), 'toolong': (‘message for long length)})
RangeValidator - 通常与 RangeField 一起使用。它有助于验证数字字段的值在最小和最大限制内。可以自定义太短和太长参数的消息。
tw2.core.RangeValidator(min = minval, max = maxval, msgs = { 'tooshort': (‘message for short length’), 'toolong': (‘message for long length)})
IntValidator - 该类派生自 RangeValidator。这通常用于验证普通文本字段中的输入是否包含整数数据。可以设置最小和最大限制以及错误消息。此外,非整数输入的错误消息可以指定为“notint”参数。
tw2.core.IntValidator(msgs = {‘notint’:’Must be Integer’})
OneOfValidator - 此验证器强制用户仅从列表中的可用选项中选择一个值。
tw2.core.OneOfValidator(values = [option1, option2,..], msgs = {‘notinlist’:’Not in List’}}
DateValidator - 对于确保用户输入是有效日期非常有用。日期格式(默认为 YMD)和错误消息可自定义。还可以指定最小和最大日期限制。DateTimeValidator 还可用于验证 DateTime 类的对象。
tw2.core.DateValidator(msgs = {format = ’%Y-%m-%d’, 'baddatetime': ('baddate', ('Must follow date format $format_str'))}
EmailValidator - 根据有效的电子邮件地址验证用户输入。该类继承自更通用的 RegexValidator。
tw2.core.EmailValidator(msgs = {'badregex': ('bademail', ('Must be a valid email address')) }
UrlValidator - 该类也是从 RegexValidator 继承的。它验证用户输入的有效 URL。
tw2.core.UrlValidator(msgs = {'badregex': ('badurl', ('Must be a valid URL’)) }
MatchValidator - 确认一个字段的值是否与另一字段匹配。当用户需要选择并确认密码字段时,这特别有用。MatchValidator 的典型用法如下所示 -
import tw2.core as twc import tw2.forms as twf class AdmissionForm(twf.Form): class child(twf.TableLayout): validator = twc.MatchValidator('pw', 'pwconfirm') pw = twf.PasswordField() pwconfirm = twf.PasswordField()
还可以构建一个复合验证器,如果任何一项检查通过,则希望验证成功。在其他情况下,您可能希望仅当输入通过所有检查时验证才能成功。为此,tw2.core 提供了 Any 和 All 验证器,它们是可扩展的CompoundValidator 的子类。
TurboGears – 闪讯
TurboGears 提供了一个非常方便的消息系统,以非侵入性的方式向用户通知信息。tg 模块中的 TGFlash 类提供对存储在普通 cookie 中的闪烁消息的支持。该类支持通过 JavaScript 在服务器端和客户端获取 Flash 消息。
当从 Python 本身使用时,可以从模板调用 TGFlash 类的 render() 方法来呈现 Flash消息。如果在 JavaScript 上使用,它会提供一个 WebFlash 对象。它公开了payload()和render()方法来获取当前的flash消息并从JavaScript中渲染它。
使用“快速启动”创建 TurboGears 项目时,它有一个 Master.html 模板。它包含该 flash 对象的变量的定义。从控制器接收到的此闪存消息的内容替换此模板中标记的占位符。
<py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with>
tg.flash_obj是 WebFlash 对象,通过包含master.html模板,它可以在任何呈现的模板中使用。该对象允许检索当前的闪存消息并显示它。
Flash 消息通过使用tg.flash()方法存储在 cookie 中(默认名称为 webflash)。然后将消息和状态参数传递给它。
tg.flash('Message', 'status')
如果调用 flash 的方法执行重定向,则 flash 将在重定向页面内可见。如果该方法直接公开模板,则 Flash 在模板本身内部将可见。
可以通过将 CSS 样式应用于状态代码来自定义 Flash 消息的外观。“快速启动”项目包含由样式表 public/css/style.css 定制的错误、警告、信息和正常状态代码。还可以添加更多带有样式的状态代码。
#flash > .warning { color: #c09853; background-color: #fcf8e3; border-color: #fbeed5; } #flash > .ok { color: #468847; background-color: #dff0d8; border-color: #d6e9c6; } #flash > .error { color: #b94a48; background-color: #f2dede; border-color: #eed3d7; } #flash > .info { color: #3a87ad; background-color: #d9edf7; border-color: #bce8f1; }
该外部样式表需要包含在模板中 -
<link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" />
任何 Flash 消息支持的配置都可以通过设置 TGFlash 对象的 configure() 方法或 app_cfg.py(在 config 文件夹中)中的参数来实现。可配置的参数是 -
先生。 | 参数及说明 |
---|---|
1 | flash.cookie_name 用于存储 flash 消息的 cookie 的名称。默认是webflash。 |
2 | flash.default_status 如果未指定则默认消息状态(默认情况下可以) |
3 | flash.模板 渲染时用作Flash 模板。 |
4 | flash.allow_html 打开/关闭 Flash 消息中的转义,默认情况下不允许 HTML。 |
5 | flash.js_call 从 JavaScript 显示 Flash 时将运行的 JavaScript 代码。默认是webflash.render() |
6 | flash.js_模板 string.Template实例用于替换对 Flash 消息的完整 JavaScript 支持。 |
pop_payload() - 函数获取当前闪存消息、状态和相关信息。获取闪现消息将删除 cookie。
render(container_id, use_js=True) - 在模板内渲染 Flash 消息或为其提供 Javascript 支持。
container_id是显示消息的 DIV,而 use_js 在将 Flash 渲染为 HTML 或供 JavaScript 使用之间切换。
status - 仅获取当前闪存状态,获取闪存状态将删除 cookie。
message - 仅获取当前的flash 消息,获取flash 消息将删除cookie。
如何制作简单的Flash消息?
在以下示例中,根控制器类中提供了 flash() 方法。它调用 flash() 消息,该消息被渲染到公开的模板 flash.html
from hello.lib.base import BaseController from tg import expose, flash, redirect, request class RootController(BaseController): @expose('hello.templates.flash') def flash(self, user = None): if user: flash(message = "Welcome "+user,status = "ok") else: flash(message = "Welcome Guest",status = "info") return {}
templates文件夹下制作flash.html的代码如下
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:py = "http://genshi.edgewall.org/" xmlns:xi = "http://www.w3.org/2001/XInclude"> <head> <title>TurboGears 2.3: Flash messages>/title> <link rel = "stylesheet" type = "text/css" media = "screen" href = "${tg.url('/css/style.css')}" /> <py:with vars = "flash = tg.flash_obj.render('flash', use_js = False)"> <div py:if = "flash" py:replace = "Markup(flash)" /> </py:with> </head> <body> <h2>Hello TurboGears</h2> </body> </html>
启动服务器,在浏览器中输入http://localhost:8080/flash?user=MVL