涡轮齿轮 - 快速指南


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

SQL炼金术

源氏

该模板引擎用于构建 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将呈现以下输出-

示例 Html 结果

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

  • 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:choosepy:whenpy: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:choosepy:when指令的使用。HTML 表单将数据发布到 /marks URL。marks ()函数将标记和结果以字典对象的形式重定向到total.html模板。结果通过/失败的条件显示是通过使用py:choosepy: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将呈现以下输出-

总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:例如

结构操作指令

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