On this page... (hide)
1. 资源推荐
- Turbogears 2.1 官方文档集:2.0 的文档内容有很多没有写全,所以建议直接读 2.1 的文档。
- Working with TurboGears:以要点分类方式整理的 TG 2.1 的文档,特别方便查找。
- 在细节组件弄不清楚的时候,建议直接查找 Pylons 的相关文档,毕竟 Turbogears2 的底层全部都是 Pylons 。
- TurboGears 2 Tutorial v0.1:TurboGears2 的一本简明教程,刚开始写,内容不算全面,用来当简明手册看还是不错。
- 一本略嫌简陋的 TG2 教程:有可能和上面这个 Tutorial 0.1 是一个东西。。
- TurboGears 2.0 版本自带的 Tutorial:最基础的入门文档,学习 TG2 必看的。
2. 基本安装
关于 virtualenv :
- 其实不一定所有 TG2 需要包都要让它的安装脚本自己去重新折腾一遍,可以用 add2virtualenv 命令(这个指令包括在 virtualenvwrapper 工具包中)让 virtualenv 使用一部分系统中已经有的公共包,比如使用系统中公用的 MySQLdb 。具体参考Help with installation of MySQLdb for Turbogears 2。
大致步骤如下:
- 安装virtualenvwrapper:pip install virtualenvwrapper
- source /usr/local/bin/virtualenvwrapper.sh (不确定这一步是否是拥有 add2virtualenv 指令所必须的),另外这一步会要求设定“WORKON_HOME”环境变量。
- add2virtualenv /opt/local/lib/python2.5/site-packages (比如我的 /opt/local/lib/python2.5/site-packages 目录下有 MacPorts 安装的 MySQLdb ,那么这样以后就可以在 virtualenv 环境下周到这个库了。)
- 如果是想引入 egg 包,那么可以类似 add2virtualenv /opt/local/lib/python2.5/site-packages/simplejson-2.0.9-py2.5-macosx-10.5-i386.egg 这样。
- 其实 add2virtualenv 指令就是把指定的路径添加到了 site-packages/virtualenv_path_extensions.pth 文件中罢了,和 easy_install 的基本原理是一样的。
3. 要点速查
3.1 表现层
Genshi 模板相关:
- Genshi 模板语法参考
- Genshi 模板中 if-else 语法的替代写法:Genshi 自身的 if 语句不支持 else ,这里介绍官方推荐的替代写法。
- 在 Genshi 中输出 HTML 代码的办法:另外还可参考How can I include literal XML in template output?
- Genshi 出现 TemplateSyntaxError: unbound prefix: line .., column .. (template.html, line ..) 错误的处理办法:其实这个错误是因为模板文件中没加 Genshi 的 xmlns 定义头造成的,加上就好了。。
- 建议用 xmllint 检查 Genshi 模板:对不完全符合标准的模板文件, Genshi 会报错,但这个错误提示并不总是很详细明确,可以手工调用 xmllint 来检查模板、发现错误。
- Genshi 模板中嵌入 Python 代码的方法:Genshi 模板中的确是可以内嵌 Python 代码的,但这不大符合 Genshi 模板本身的精神,也会给系统的可维护性带来不良影响,因此应尽可能少用这种方式。
- Genshi 模板能够默认调用的上下文变量及含义汇总
- WebOb Reference:Genshi 模板中 request 和 response 变量提供的具体方法需要参考 WebOb 的这个文档。
- helpers.py 的习惯用法:helpers.py 文件中的内容可以直接在 Genshi 模板中通过 h 或者 helpers 关键字调用,可以将模板中常用的公共函数放在这里面。TG2 自动生成的 helpers.py 中包括了对webhelpers包中一些函数的引用。
- Helper functions for use in Genshi templates:Genshi 项目自身提供的几个 Helper 函数,比如数据分组、分页、计数等等。
- XPath 是理解 Genshi 、用好 Genshi 的重要基础。虽然不懂 XPath 仍然可以用 Genshi ,但在深入 Genshi 的时候会遇到瓶颈,导致很多“笨办法”大行其道。不过也要注意, Genshi 对 XPath 标准支持不够完整,参考 Using XPath in Genshi 。
- 如何在 Turbogears2 中利用 Genshi 模板输出 XML 数据
- TG2 中智能动态菜单的实现
表单自动生成:
- 目前推崇使用FormAlchemy配合fa.jquery来搞。
- 另外大致有 ToscaWidgets, FormEncode, and Sprox 三个方案可选,具体的需要继续研究。
- Pylons 文档中提及的表单自动生成方法
3.2 Controller 层
- CRUD 风格的应用,可以利用 CrudRestController自动生成。
- 参考The Lookup Method,可以很容易实现 RESTful 风格的 Web 应用。
- Cookie 访问方法参考 What is a good way to handle cookies in Pylons? 以及 Setting cookies and response headers 。
3.3 Model 层
- SQLAlchemy 0.5.8 官方文档
- SQLAlchemy 自身提供的跨平台数据类型
- SQLAlchemy 中 MySQL 特有的数据类型
- 在 TG2 环境之外调用 Model 的方法
- 调整、定制 Model 的属性:(Model 的属性一般对应数据库表中的一列,在处理遗留数据和复杂需求时难免要对 Model 和数据库表的对应关系做一些定制)SQLAlchemy 不但可以为属性建立别名,甚至可以利用 sqlalchemy.orm.synonym 把函数处理的输出结果封装成属性的形式来用。具体参照Mapper Properties
- SATrigger?:以往数据库自动更新关联数据往往是依靠触发器的,但触发器中的性能问题难以调试,而且在不同数据库引擎中编写的具体语法也会有所差别,其实在 ORM 中完全可以实现类似触发器的效果。
- 有时会遇到一些 Model 实例没法 Cache 的情况,这本质是因为这些对象没法 pickle ,可参考文档 Why can't I pickle this object? 中提供的解决方案。大致来说,主要是为对象增加以下两个接口的实现:
def __getstate__(self): return self.__dict__
def __setstate__(self, d): self.__dict__.update(d)
3.4 Paster 脚本
- paster shell development.ini 这个指令需要在 development.ini 目录下执行,否则会报错找不到 shell 命令,这是因为 paster shell 需要用到 egg-info 目录下的信息。
3.5 更多解决方案
- TG2 下实现浏览器端实时消息推送的解决方案:其主要基于 Orbited 。
- turbomail:Python 发邮件的最靠谱的解决方案。其官方文档讲解了如何集成到 Pylons 里头, TG2 估计路子也差不多。
4. 服务部署
4.1 基本部署
- TurboGears 2 Deployment:描述了 TG2 部署到 lighttpd 上的详细方法。
- TG2 部署到 Apache 和 Nginx 上的方法在官方文档有详细说明。
4.2 部署优化
- 静态文件处理:部署的基本原则是静态文件要交给 httpd 服务器直接处理。
- gzip 压缩:我使用 fast-cgi 方式把 TG2 部署在 lighttpd 上时,lighty 的 gzip 压缩模块是无法处理 TG2 传过来的页面的。暂时利用 paste 的 gzipper 中间件来实现对 TG2 输出内容的压缩。于是现在我的 dispatch.py 大致是这样的:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
prev_sys_path = list(sys.path)
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
import os, sys
sys.path.append('/srv/www/lighttpd/tg2env/ourspass')
from paste.deploy import loadapp
wsgi_app = loadapp('config:/srv/www/lighttpd/tg2env/ourspass/production.ini')
from paste.gzipper import make_gzip_middleware
wsgi_app = make_gzip_middleware(wsgi_app, None)
if __name__ == '__main__':
from flup.server.fcgi import WSGIServer
WSGIServer(wsgi_app, minSpare=1, maxSpare=5, maxThreads=50).run()
5. 架构调优
5.1 面向应用程序集群的 Session 支持
一旦对 Web App 实施分布式集群来提高处理能力,则 Session 信息的同步和存储会成为一个麻烦的问题。虽然也可以干脆将 Session 存储在 Cookie 里来解决同步问题,但这样会有浏览器兼容性、数据容量、存取性能等方面的一些问题。
考虑使用高性能高并发的数据存储服务来保存 Session,参考Pylons with Tokyo Cabinet Beaker Sessions