|
阅读本文之后,您就能够使用 Python 脚本和 Cheetah 模板生成任何种类的基于文本的内容。Cheetah 模板易于了解和维护,并且可以帮助您将文档的静态部分与动态部分分离。 一个过于臃肿的模板系统 “使用 SQLObject 连接数据库与 Python”中提到各种用于 Python 的开源对象关联式映射库。Python 编程人员喜欢按照自己的方式办事,这带来了许多附属成果。不过,所有这些努力常常汇集成一个对所有人都非常有益的包。 同样的模式对模板系统却已经过时:表示静态文本的方式将像窗体一样被扩充,这样可以随后插入动态元素。官方的 Python Wiki 链接了近 20 个模板系统,这些只是一些主要的模板系统。还有更多的模板系统,随 Python 一起打包的是一些基本的模板系统,这些模板系统将在简单的情形下工作。 本文将描述模板系统可以解决的问题。还将描述 Cheetah,它是已经设计出来的最好的 Python 模板系统。本文假定您具备 Python 方面的基础知识,但不具备模板系统及其用处方面的知识。 基本的模板概念 假定您正在为一家在线商店编写一个 Web 应用程序。您需要一些类来表示这家商店和购买过程的某些方面:库存物品、客户和客户所下的定单,等等。这些类的实例可能对应于数据库中的行,并且它们被用来
为什么要使用模板系统? 如果没有模板系统,那么就要使用 Python 代码生成类似示例电子邮件消息的文本片段。还要编写附加到字符串列表的逻辑或为类文件对象编写的逻辑。例如,以下代码可以生成上面所述的电子邮件: 清单 3. 生成电子邮件 from DummyObjects import dummyUser, dummyOrder l = [] l.append('Hello, ') l.append(dummyUser.firstName) l.append('.\n\nYour order (#') l.append(str(dummyOrder.id)) l.append(') has shipped:\n') for purchased, quantity in dummyOrder.purchased.items(): l.append(' ') l.append(purchased.name) l.append(': ') l.append(str(quantity)) l.append(' unit(s)\n') l.append('\nYour tracking number is ') l.append(dummyOrder.trackingNumber) l.append('.') print ''.join(l) 不幸的是,这个代码不像它的输出那样好。通过查看此代码,难以看出电子邮件消息的结构。许多代码是重复的(例如,有许多对列表的 append() 方法的调用),这为错误创造了空间。最后,团队的 UI 设计人员可能宁愿编辑类似上面描述的抽象模板那样的东西,也不愿意编辑这种 Python 代码。由于上述这些原因,开发人员转向模板系统。 有 Python 的内置模板系统就足够了吗? Python 提供了少许内置模板系统,它们在简单情况下工作得很好。很长时间以来,Python 一直拥有一些简单的模板系统,它们有一些易于让人理解的格式,这些格式令人回想起 C 的 printf() 字符串格式: 清单 4. Python 的内置模板系统 from DummyObjects import dummyUser, dummyOrder print 'Hello, %s.\n\nYour order (#%d) has shipped:' % (dummyUser.firstName, dummyOrder.id) print 'Hello, %(firstName)s.\n\nYour order (#%(orderID)d) has shipped:' % \ {'firstName' : dummyUser.firstName, 'orderID' : dummyOrder.id}
Python V2.4 引入了一个具有看起来更现代的格式的模板系统。变量名称是通过添加美元符号($)作为前缀来指定的;这类似于 Perl、PHP、大多数 shell 语言和 Cheetah: 清单 5. Python V2.4 的内置模板系统 from string import Template from DummyObjects import dummyUser, dummyOrder t = Template('Hello, $firstName.\n\nYour order (#$orderID) has shipped:') t.substitute({'firstName' : dummyUser.firstName, 'orderID' : dummyOrder.id}) 这些模板系统都有两个重要的缺点。 它们的模板定义都不能调用任何方法,或者访问 dummyUser 和 dummyOrder 对象的任何成员。不能将 dummyUser.firstName 放入模板定义中,必须将它放入应用于模板定义的映射中。所有将插入静态模板定义中的动态信息都必须首先拆分为基本的 Python 数据类型。 这些模板系统没有流控制 —— 没有循环或条件。以前的那些例子恰好在必须按顺序在项上进行迭代之前停止执行,并且有一个好的理由:它们使用的模板系统无法在模板定义内部进行这种迭代。您需要编写 Python 代码在这些项上按顺序进行迭代,将多个字符串连接在一起(可能使用中间模板),并以称为 itemsOrdered 的单个字符串的形式向模板系统提供最终结果。循环本身是电子邮件主体的静态部分的一部分 —— 无论处理什么样的用户和定单,其工作方式是相同的 —— 但无法将它应用到静态模板定义中。 多数可用于 Python 的附加模板系统试图弥补这两个缺点。其中最好的替代是 Cheetah。 <下一页> |