gashero的Pylons笔记
gashero的Pylons笔记
- 1 《Pylons初探》笔记
- 2 Pylons首页信息
- 3 安装Pylons
- 4 启动Pylons之后,主页上的例子
- 5 《Getting Started》比《Pylons初探》增加的内容
- 6 《Windows用户安装后必读》笔记
- 7 调试中发现的问题
1 《Pylons初探》笔记
1.1 安装
-
下载安装工具ez_setup.py
-
命令行运行如下:
python ez_setup.py Pylons
-
设置环境变量
pyth -> C:Python24Scripts
-
运行命令paster,如果运行成功会出现如下结果:
Usage: C:\Python24\Scripts\paster-script.py COMMAND ... ...
1.2 开始动手
-
新建一个Pylons工程:
paster create --template=pylons helloworld
运行成功后产生如下结果:
Selected and implied templates:: pylons#pylons Pylons application template ... ...
-
运行这个新建的工程
-
启动服务器:
cd helloworld paster serve --reload development.ini
-
访问 http://127.0.0.1:5000/ 将会看到欢迎页面
-
在 helloworld/public 目录下创建test.html文件,内容如下:
<html> <body> Hello world! </body> </html>
-
访问 http://127.0.0.1:5000/test.html 看到结果。
-
-
禁用调试功能
将development.ini文件中的如下行的注释删除:
# set debug=false
-
创建一个控制器,修改Routes
-
命令行运行:
paster controller hello
-
修改 helloworld/controllers/hello.py ,代码如下:
from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('hello world')
-
修改 helloworld/config/routing.py ,代码如下:
""" Setup your Routes options here """ import sys,os from routes import Mapper def make_map(global_conf={}, app_conf={}): root_path=os.path.dirname(os.path.dirname(\ os.path.abspath(__file__))) map=Mapper(directory=os.path.join(root_path,'controllers')) # 这个route handle用来显示错误页面 map.connect('error/:action/:id', controller='error') #定义自己的route,可以定义很多细节 #更多有用的信息参考http://routes.groovie.org/docs/ map.connect('',controller='hello',action='index') map.connect(':controller/:action/:id') map.connect('*url',controller='template',action='view') return map
-
删除 public/index.html 。访问 http://127.0.0.1:5000/hello 和 http://127.0.0.1:5000/ 将会看到 Hello world。
-
-
模板和请求周期
-
创建模板文件 helloworld/templates/serverinfo.myt ,代码如下:
<p>Hi, here's the server environment: <br /> <% str(request.environ) %></p> <p> and here's the URL you called: <% h.url_for() %> </p>
-
修改 helloworld/controllers/hello.py ,代码如下:
from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('hello world') def serverinfo(self): return render_response('/serverinfo.myt')
-
访问 http://127.0.0.1:5000/hello/serverinfo ,可以看到如下结果:
Hi, here's the server environment: ... ... and here's the URL you called: /hello/serverinfo
-
-
使用Session,代码如下:
def serverinfo(self): session['name']='George' session.save() return render_response('/serverinfo.myt')
-
控制器变量和模板全局变量
控制器变量
-
修改 helloworld/controllers/hello.py ,代码如下:
from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('hello world') def serverinfo(self): c.value=2 return render_response('/serverinfo.myt')
-
修改 helloworld/templates/serverinfo.myt ,代码如下:
<p> The value of <tt>c.value</tt> is: <% c.value %>
-
访问 http://127.0.0.1:5000/hello/serverinfo ,可以看到 The value of c.value is: 2 。
模板全局变量
-
修改 lib/app_globals.py ,代码如下:
class Globals(object): def __init__(self,defaults,app,**extra): self.message='Hello' def __del__(self): """ 将清空代码放在这里 """ pass
-
修改 helloworld/controllers/hello.py ,代码如下:
from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('hello world') def serverinfo(self): c.value=2 return render_response('/serverinfo.myt') def app_globals_test(self): resp=Response() if g.message=='Hello': resp.write(g.message) g.message='Hello world!' else: resp.write(g.message) return resp
-
访问 http://127.0.0.1:5000/hello/app_globals_test/ ,可以看到 Hello world! 。
-
2 Pylons首页信息
Pylons的最新版本为0.9.4.1,发布于2007-01-06。这是一个bugfix版本,原版本0.9.4发布于2006-12-29。上面那篇文章的对应版本为0.9.3,看来差的 还不是太远。
Pylons是一个轻量级的WEB开发框架,强调灵活性和快速开发。
2.1 为什么使用Pylons
Pylons结合了Ruby、Python和Perl的优点,提供了结构化的,但是却非常灵活的Python WEB开发框架。他也是首个支持新出现的WSGI标准的项目,在需要时允许广泛的重用和移植。Pylons的目标是使得WEB开发更加快速、灵活和简单。
2.2 与其他组件一起使用
Pylons基于 Paste 并支持其他常见的Python组件:
- 模型: SQLAlchemy 、 SQLObject ,和普通的DB-API
- 模板: Myghty 、 Kid 、 Cheetah ,或者其他你喜欢的,如 Buffet
- AJAX: Rails风格的 WebHelpers 基于 Prototype 或者 Mochikit 、 Dojo 等等
- 请求发布: 缺省为 Routes ,也可以选择其他的
2.3 最新的入门教程
- 如何使用 Pylons 快速编写一个博客 Tutorial
- 使用AJAX快速入门 AjaxGettingStarted
- 模仿 Flickr 的例子 flickrsearch
- 使用 Apache 、 FastCGI 和 mod_rewrite 进行产品级开发 FastCGI
2.4 有用的资源
你可能对 使用了Pylons的站点 感兴趣。如果你需要的信息在 文档 中是没有的,则可以参考 wiki ,这里的信息会有更快的更新,并且有更加全面的资源。当然,你也可以自己 添加文章 。
2.5 顶部导航栏链接
主页 文档 wiki 社区 FAQ 安装 Pastebin 查找文档
3 安装Pylons
首先,Windows上的Python2.3用户需要先安装 subprocess.exe (下载失效),而Python2.4用户则不需要。所有的Windows用户在安装完成后需要研读 安装后必读 ,而Ubuntu和Debian用户则需要安装 python-dev 包。
3.1 系统级安装
如果需要安装好的Pylons被所有用户所使用,就需要使用root帐户。如果你已经拥有了easy install,则可以执行如下命令:
$ easy_install Pylons
Note
偶尔python.org会挂掉。这时仍然可以用本地的文件来安装Pylons及其以来的包。:
easy_install -f http://pylonshq.com/download/ Pylons
这样会自动安装最新版本的包。如果你正在使用一个旧版本,则可以指定版本:
easy_install -f http://pylonshq.com/download/0.8.2/ Pylons
否则,先下载 easy install ,地址为 http://peak.telecommunity.com/dist/ez_setup.py 。然后运行:
$ python ez_setup.py Pylons
Note
你可以选择安装一个其他的扩展(extra),如下:
$ easy_install Pylons[extra]
pudge :支持构建构建文档,查看 为应用添加文档 。需要注意的是很多文档工具还处于开发中,并不是很稳定。
genshi :支持使用 genshi 模板,查看 使用其他模板语言
cheetah :支持使用 cheetah 模板,查看 使用其他模板语言
kid :支持使用 kid 模板,查看 使用其他模板语言
full :如上所有的
3.2 自定义安装位置
如果需要自定义安装位置,则可以参考:
http://peak.telecommunity.com/DevCenter/EasyInstall#custom-installation-locations
查看Easy Install的文档可以了解Pylons是否是安装为系统级。
http://peak.telecommunity.com/DevCenter/EasyInstall
3.3 升级安装
升级到最新版本使用:
$ easy_install -U Pylons
3.4 工作于前沿(Living on the Cutting Edge)
如果不满意于最新的发行版,或者希望使用源代码工作,可以使用最新的开发版本:
http://pylonshq.com/docs/0.9.4.1/pylonsdev.html
3.5 Easy Install 的问题
有时候如果Pylons依赖的包安装失败会导致Easy Install出错。这时候确保 setuptools 是最新版本,使用如下命令:
$ easy_install -U setuptools
然后再次尝试安装Pylons,如果再次安装失败,就先手动安装Pylons依赖的软件包,然后再安装Pylons。例如,如果你安装Myghty时,可以指定最新版本的位置:
$ easy_install -U -f http://pylonshq.com/download/ Myghty
或者你也可以直接使用URL上的发行版来安装。这时我们将会从cheeseshop安装Myghty 1.1,但是你必须确保安装当前Pylons版本所使用的文件:
$ easy_install -U http://cheeseshop.python.org/packages/source/M/Myghty/Myghty-1.1.tar.gz#md5=5865361811dca4054f1ec60ac32ee965
3.6 软件包注释
Pylons使用的 Cheetah、docutils、elementtree、nose等等软件包多多少少的被 James Gardner 修改过,所以可以被setuptools和Python2.3方便的安装和使用。这些软件包的某些安装指令需要手动调整。如果你不打算使用Pylons提供的这些软件包版本,Pylons开发组并不确保可以工作。
4 启动Pylons之后,主页上的例子
helloworld/public/ 目录在运行之前搜索需要显示的静态文件。删除文件 helloworld/public/index.html 然后修改路由(Route) helloworld/config/routing.py 成如下的样子:
map.connect('',controller='hello',action='index')
新建一个hello.py文件,内容如下:
# helloworld/controllers/hello.py from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('Hello world')
然后访问 http://127.0.0.1:5000/hello 可以看到结果。
使用模板的例子,Myghty模板:
# helloworld/templates/serverinfo.myt <p>Hi, here's the server environment: <br /> <% str(request.environ) %></p> <p>here's the URL you called: <% h.url_for() %> </p> <p>and here's the name you set: <% c.name %></p>
然后将这些添加到你的hello控制器类当中:
def serverinfo(self): c.name='The Black Knight' return render_response('/serverinfo.myt')
然后通过 http://127.0.0.1:5000/hello/serverinfo 来访问。
5 《Getting Started》比《Pylons初探》增加的内容
尽管《Pylons初探》就是翻译自《Getting Started》,但是版本并不相同。现在版本比原版本增加了一些内容。
http://pylonshq.com/docs/0.9.4.1/getting_started.html
5.1 简介
如果尚未完成安装,阅读 安装过程 。这个文档引导用户快速入门。
5.2 创建一个Pylons工程
Pylons使用Paste创建和部署工程,当然还可以创建控制器及其单元测试。
创建一个新工程叫做 helloworld 使用如下命令:
paster create --template=pylons helloworld
Note
Windows用户必须先配置 PATH 环境变量在 安装后必读 。至少应该可以在控制台中得到 paster 的路径。
这将会创建一个基本的工程目录,目录具有如下结构:
-helloworld -data -helloworld -helloworld.egg-info -Various files including paste_deploy_config.ini_tmpl -development.ini -setup.cfg -setup.py
文件 setup.py 用于创建自安装包,叫做 egg 。 egg 可以看作等同于Java中的 .jar 文件。而 setup.cfg 包含了工程的其他信息,目录 helloworld.egg-info 包含关于egg的信息,包括一个 paste_deploy_config.ini_tmpl 文件用作工程使用的配置模板,可以用 paster make-config 命令来通过这个模板创建配置文件。发行和部署工程可以参考 发行工程 ,而最终用户可以参考 安装应用 。
注意 data 目录,这个目录可以被 development.ini 文件所配置,并用于保存缓存数据和会话。
helloworld 中的 helloworld 目录用于放置应用程序的特定文件。目录结构如下:
-helloworld -helloworld -config -controllers -docs -i18n -lib -models -public -templates -tests -__init__.py -websetup.py
config 目录包含了WEB应用的配置选项。
controllers 目录放置控制器。控制器是程序的核心,决定了装入哪些数据,和如何显示。
docs 目录用于放置程序的文档。你可以使用 setup.py pudge 来将他们转换为HTML。
i18n 目录用来放置多语言信息编目。
lib 目录用来放置各个控制器之间的共享模块,第三方代码,或者其他合适的代码。
models 目录用来放置模型对象,比如ORM使用的类。在 models/__init__.py 中的对象定义将会被装入并作为模型 model.YourObject 。数据库的配置字符串保存在 development.ini 文件。
public 目录用来放置HTML、图像、JavaScript、CSS等等静态文件。有如apache的htdocs目录。
tests 目录用来放置控制器等等的单元测试。控制器的单元测试使用Nose和 paste.fixture 。
templates 目录来保存模板。模板包含混合的静态文本和Python代码,用来生成HTML文档。Pylons使用Myghty模板作为缺省,但是同时支持Cheetah、Kid等等其他多种模板,这些需要通过Buffet来调用。查看 如何使用其他模板 。
__init__.py 文集那将 helloworld 目录作为一个Python包来发布。
websetup.py 文件包含了用户在运行 paster setup-app 时运行的代码,参考 安装应用 。如果希望在应用执行之前运行一些代码,这里比较好。
5.3 尝试使用模板
我们可以尝试一个模板工程如下:
$ cd helloworld $ paster serve --reload development.ini
这些命令会使用配置development.ini进行启动并提供Pylons服务。
选项 –reload 会在Python代码或 development.ini 文件发生改变时自动重启服务器。这在开发中是非常有用的。
如果访问 http://127.0.0.1:5000/ 你可以看到欢迎页面( 127.0.0.1 是本机IP),但是可以通过 development.ini 文件来修改。
尝试创建一个新文件 test.html 在目录 helloworld/public 中,内容如下:
<html> <body> Hello world! </body> </html>
如果访问 http://127.0.0.1:5000/test.html 可以看到 Hello World! 这个信息。任何在 public 目录下的文件都回按照相同的名字对外提供服务,Pylons有个选项可以决定从 public 目录返回,还是从代码返回。这个行为可以通过修改 config/middleware.py 文件中的 Cascade 的顺序来改变。
5.4 交互调试器
交互调试器是开发中的强大工具。他在使用 development.ini 作为配置时是默认启用的。当启用时,他允许通过一个WEB页面寻找错误发生的位置。在产品环境中调试器将会降低安全级别,所以通过 paster make-config 生成的产品环境配置文件需要关闭调试器。
关闭调试器,取消如下的注释,在 development.ini 文件的 [app:main] 节中:
# set debug=false
改为:
set debug=false
然后。将debug设置为false就是为了在产品环境提高安全系数。
更多相关信息参考 交互调试器 文档。
5.5 创建控制器并修改URL路由
你现在可以创建一个自己的WEB应用了。首先给hello world创建一个控制器:
$ paster controller hello
命令 paster 会创建 controllers/hello.py 文件,并同时创建其单元测试文件 helloworld/tests/functional/test_hello.py 用来运行这个控制器的单元测试。
如下是用于在 http://127.0.0.1:5000/hello 打印 ‘Hello world’ 的简单控制器代码。将这些代码放入 helloworld/controllers/hello.py 文件中:
from helloworld.lib.base import * class HelloController(BaseController): def index(self): return Response('Hello world')
Pylons使用一个强大的并且灵活的URL路由来控制代码和URL的映射。
我们希望同时在 http://127.0.0.1:5000/hello 和 http://127.0.0.1:5000/ 下显示,可以通过如下路由。将如下的行添加到配置文件 helloworld/config/routing.py ,如下:
map.connect('',controller='hello',action='index') map.connect(':controller/:action/:id') map.connect('*url',controller='template',action='view')
这样就可以将空URL匹配到 hello 控制器的 index 行为上,否则就按照 controller/action/id 的方式匹配,当然要确保这些可以匹配到。如果确实匹配不到了,就转到 templates 控制器的 view 行为,显示404错误。
改变了URL的路由之后必须重启服务器。但是如果你有开启 --reload 选项则会自动重启服务器,要不就要手动关闭和启动。
Note
Myghty模板的改变不需要重启服务器,也不需要 --reload 就可以起效。
访问 http://127.0.0.1:5000/hello 和 http://127.0.0.1:5000/ 可以看到第一个显示 Hello world ,而第二个显示从前的欢迎页面。这是因为在 public 目录下的静态文件要优先于代码被显示。
删除文件 public/index.html 可以得到预期效果。更多信息参考 URL路由手册 。
5.6 模板和请求周期
当你的控制器的方法被WSGI应用所请求并返回Response对象时,如果希望使用模板返回,可以使用 command 命令,或者 render_response 命令。随之会处理模板并生成响应(Response)对象。
Note
如果希望获得更多关于 render 和 render_reponse 的信息,参考 Pylons模板API
下面的例子模板,使用Myghty,打印一些信息。
创建一个模板文件 helloworld/templates/serverinfo.myt ,包含如下内容:
<p>Hi, here's the server environment: <br /> <% str(request.environ) %></p> <p> and here's the URL you called: <% h.url_for() %> </p>
使用这个模板,在 helloworld 的HelloController控制器添加新方法如下:
def serverinfo(self): return render_response('/serverinfo.myt')
函数 render_response('/serverinfo.myt') 会使用默认引擎(Myghty)处理模板。
如果服务器仍然在运行,可以查看 http://127.0.0.1:5000/hello/serverinfo 。
也可以简单的重启服务器,在helloworld目录执行 paster serve --reload development.ini 。
5.7 使用Sessions
会话的处理来自应用程序的 Beaker middleware ,其包含Myghty的容器API。提供了健壮和强大的Session和缓存能力。
使用Session是很容易的,如下是保存Session的例子:
def serverinfo(self): session['name']='George' session.save() return render_response('/serverinfo.myt')
Session的选项可以通过 development.ini 来定制,并且使用相同的名字,详见 Myghty docs for sessions 。
Note
记住每次调用 session.save() 在返回相应之前来确保Session的保存。
5.8 控制器变量和模板全局变量
5.8.1 Pylons全局变量
为了方便,有少数几个通过导入 lib.base 就可以使用的全局变量,你可以在控制器中随意使用:
sessioin :存储Session数据,参考 Myghty Session docs 。
request :请求对象。
Response :响应类,控制器一般来说应该返回这个类的实例。
abort :用于中断请求,并发送 HTTPException ,可以附带状态码。
redirect_to :通过HTTP 302状态码来重定向浏览器到其他地址的函数,通过HTTPException实现。
render :用来使用模板生成字符串的函数。
render_response :用来使用模板生成 Response 对象的函数,相当于 Response(render(...)) 。
h :用于引用Pylons的其他工具函数。缺省时,Pylons会将工具函数装入自 Web Helper 包。阅读文档时应该记住这些函数都可以通过 h 来引用。在Pylons下面通过这个作为命名空间。
c :用来向模板传递变量。
g :应用程序全局变量对象,可持续的。
5.8.2 传递变量到模板
Pylons控制器被每个请求创建一次。这意味着你可以在 self 上面绑定需要使用的变量。当然,这样做不太好跟踪,除非你需要传递到模板。如果希望传递传递数据到模板,可以使用变量 c 。因为Myghty模板默认就是使用 c 作为全局变量的。下面是使用的例子:
def serverinfo(self): c.value=2 return render_response('/serverinfo.myt')
然后修改 templates 目录中的模板 serverinfo.myt 文件成如下:
<p>The value of <tt>c.value</tt> is: <% c.value %>
Note
c对象在其他模板语言中也是适用的。
你可以看到打印出来的 2 。当访问c的属性不存在时,不会发生错误,而是返回空字符串。这对控制响应行为很有用。例如:
<p>Hi there <% c.name or c.full_name or "Joe Smith" %>
Warning
不要随意设置以 “_” 开头的c的属性。c和其他很多全局变量都是 StackedObjectProxies 类的成员。这可能会与已有的内置方法发生冲突,导致一些难于调试的问题。
c对象在每次请求时都回初始化,所以不需要担心控制器使用了先前请求的旧值。
5.8.3 应用程序全局对象和持续对象
某些场合需要在各个控制器之间共享一些信息而不会在每个请求中重启。例如在应用程序启动时开启一个TCP连接。你可以通过 g 变量。
g 变量是一个 Globals 类的实例在文件 lib/app_globals.py 中。在 __init__() 中设置的属性对 g 来说都是应用级别的全局属性。在任何一个请求中对g的某个属性的修改都会保持下来。在请求中设置全局变量时必须小心。
下例是如何使用 g 变量。首先修改 lib/app_globals.py Globals 类,把 __init__() 方法如下:
def __init__(self,global_conf,app_conf,**extra): self.message='Hello'
然后添加一个新方法到 helloworld/controllers/hello.py 如下:
def app_globals_test(self): resp=Response() if g.message=='Hello': resp.write(g.message) g.message='Hello World!' else: resp.write(g.message) return resp
这时如果运行服务器在 http://127.0.0.1:5000/hello/app_globals_test ,你可以看到信息 Hello 。如果再次访问,将会改变到 Hello World! ,然后就保持这样的改变了,因为在首次请求时,变量就已经改变了。
__init__() 方法需要参数 global_conf 和 app_conf ,这些配置保存在文件 development.ini 中。这意味着可以在这里就设置全局变量。注意在第一个请求没有建立之前不可以设置变量c和h。
可以给全局变量添加 __del__() 方法,确保在程序退出时执行。
6 《Windows用户安装后必读》笔记
7 调试中发现的问题
7.1 URL映射的定义
必须在一开始就进行URL映射的定义,否则无法从URL上访问到自己的模块。在文件 config/routing.py 中定义。定义格式如下:
map.connect('urlpath',controller='controller_name',action='index')
其中的action是干什么是不知道的,重要的只是指定URL和控制器。而且要注意,这个定义必须写在 make_map() 函数中,并且必须在如下的两个语句之前定义,因为这两个语句会尽可能匹配多的URL,放在这后面不会起作用:
map.connect(':controller/:action/:id') map.connect('*url',controller='template',action='view')
当然,这种使用URL映射的方式,可以很好自定义URL的样式。
另外,只要手动重启服务器,不去 routing.py 定义URL映射,也是可以直接使用模块名来访问的。当然,这个所谓模块名是不包含 .py 的。
7.2 参数传递,方法参数传递
Pylons用于暴露的方法是允许接受参数的,当然,如果硬是不传递,也没有设置默认值的时候会由Pylons好心的传递一个None过来。这里有个例子:
class HappyController(...): def test(self,id): return Response('test'+id)
当然,顶层类是使用 paster controller happy 自动生成的,所以在URL中也是使用 happy 这个词的。而 test 则是其暴露出来供访问的方法。这时有几个URL可供调用,结果分别为:
URL | 解释 |
---|---|
/happy/test | 返回异常,报告id为None不可以连接字符串 |
/happy/test/ | 返回异常,报告id为None不可以连接字符串 |
/happy/test/50 | id得到参数50,返回 test50 |
当然这里注意,这个暴露方法参数只是通过URL的分级方式提供的,而问号之后的查询参数是不会传递到这里的。
还要注意routing.py中的一句:
map.connect(':controller/:action/:id')
这句的意思是允许以 控制器名/方法名/id 的方法来调用,作为一种默认的调用方法。而注意这个 :id ,就是说,方法的参数名只能是 id ,如果使用其他的则会发生错误。
7.3 共享模块代码
工程目录中的lib目录可以用于放置一些共享模块。调用的方法么,举个例子,比如有个模块的文件名是helloworld/lib/testunit.py,那么导入语句就可以写作:
import helloworld.lib.testunit
这样,可以在lib目录中放置数据库访问模块等等,多种东东。