Modified:
trunk/doc/agile_python/ch01-preface.xml
trunk/doc/agile_python/ch02-model-tdd.xml
trunk/doc/agile_python/ch03-pylons.xml
trunk/doc/agile_python/index.xml
Log:
Pylons 升级为 0.9.7,修改了 WebHelpers 以及 routing 相关内容
已修改: trunk/doc/agile_python/ch01-preface.xml
===================================================================
--- trunk/doc/agile_python/ch01-preface.xml 2008-09-12 10:35:00 UTC (rev 91)
+++ trunk/doc/agile_python/ch01-preface.xml 2008-09-12 15:20:13 UTC (rev 92)
@@ -13,7 +13,7 @@
项目首页:<ulink url="http://pySvnManager.sf.net"/>。该项目从一开始,
就采用了测试驱动开发(TDD)技术,通过一系列的迭代最终敏捷的实现了预期的需求。</para>
- <para>在该项目中采用了Python最新流行的MVC框架:Pylons。并在 Web 页面中大量使用了
+ <para>在该项目中采用了 Python 最新流行的 MVC 框架:Pylons。并在 Web 页面中大量使用了
AJAX 技术。本文涉及到的技术术语有:敏捷, TDD, MVC, 单元测试, 代码覆盖测试,
AJAX, 重构, i18n, 开放源代码。</para>
@@ -86,8 +86,8 @@
<para>其中1和2的错误会造成Subversion服务中断故障!3和4的问题如果不经过测试很难发现!
在我们为客户实施Subversion技术支持服务过程中,发现了用户迫切需要容错性强的
- 授权管理工具,于是便有了开发图形化管理界面的打算。选择Python是因为Python语言的魅力
- 以及Python开发过程的高效。</para>
+ 授权管理工具,于是便有了开发图形化管理界面的打算。选择 Python 是因为 Python
+ 语言的魅力以及 Python 开发过程的高效。</para>
</sect2>
@@ -113,16 +113,16 @@
<para>理论上很简单的东西,却奈何不了复杂的现实:</para>
- <para>在项目刚刚开发完成,就出现了相当长一段时间的 SourceForge.net 无法访问!
+ <para>在项目刚刚开发完成,就出现了相当长一段时间的 <uri>SourceForge.net</uri> 无法访问!
导致 <command>easy_install</command> 为了搜索最新版本,在连接到
- <ulink url="http://SourceForge.net"/> 时发生了死锁而阻塞。
- 虽然我打算把项目移到别处,但发现一些依赖的包如: python-ldap
- 也是要访问 SourceForge.net网站。因此我取消了搬家的打算,耐心且无助的等待解封。
+ <ulink url="http://pysvnmanager.sourceforge.net"/> 时发生了死锁而阻塞。
+ 虽然我打算把项目移到别处,但发现一些依赖的包如: <package>python-ldap</package>
+ 也是要访问 <uri>SourceForge.net</uri> 网站。因此我取消了搬家的打算,耐心且无助的等待解封。
同时将代码镜像在网址:<ulink url="http://svn.worldhello.net/svn/pysvnmanager"/>
- 上,供不能访问 <ulink url="http://SourceForge.net"/> 的用户参考。</para>
+ 上,供不能访问 <ulink url="http://pysvnmanager.sourceforge.net"/> 的用户参考。</para>
<para>如果遇到阻塞,则需要花费更多的时间,手工下载软件包。<command>easy_install</command>
- 也可以安装下载到本地的软件包。</para>
+ 也可以安装已经下载到本地的软件包。</para>
<screen>
$ <emphasis>wget http://pypi.python.org/packages/source/p/pySvnManager/pySvnManager... </emphasis>
@@ -169,25 +169,25 @@
<itemizedlist>
<listitem>
- <para><emphasis>config.ini :</emphasis>
+ <para><emphasis><filename>config.ini</filename> :</emphasis>
应用默认运行于5000端口,可以在此文件中定制</para>
</listitem>
<listitem>
- <para><emphasis>config/localconfig.py :</emphasis>
+ <para><emphasis><filename>config/localconfig.py</filename> :</emphasis>
- 设置应用缺省的认证方式,缺省用config/svn.passwd口令认证</para>
+ 设置应用缺省的认证方式,缺省用 <quote><filename>config/svn.passwd</filename></quote> 口令认证</para>
</listitem>
<listitem>
- <para><emphasis>config/svn.passwd :</emphasis>
+ <para><emphasis><filename>config/svn.passwd</filename> :</emphasis>
缺省该口令文件内所有用户的口令均为 "guess"</para>
</listitem>
<listitem>
- <para><emphasis>config/svn.access :</emphasis>
+ <para><emphasis><filename>config/svn.access</filename> :</emphasis>
svn路径授权文件,本应用要处理的文件。注意该文件开头的注释是版本号和版本库管理员帐号设置,
不要随意删除!</para>
已修改: trunk/doc/agile_python/ch02-model-tdd.xml
===================================================================
--- trunk/doc/agile_python/ch02-model-tdd.xml 2008-09-12 10:35:00 UTC (rev 91)
+++ trunk/doc/agile_python/ch02-model-tdd.xml 2008-09-12 15:20:13 UTC (rev 92)
@@ -11,7 +11,9 @@
<para><emphasis>忘记Web吧:</emphasis></para>
<para>我们要开发出一套Web应用,但首先要忘掉Web。这看似矛盾,却正是MVC的要求和精髓。
- 即对核心算法进行抽象,先实现Model,之后再去考虑Controller(控制器)和View(Web展现)。</para>
+ 即对核心算法进行抽象,先实现 <literal>Model</literal>,之后再去考虑
+ <literal>Controller</literal>(控制器)和
+ <literal>View</literal>(Web展现)。</para>
<para><emphasis>忘记详细设计吧:</emphasis></para>
@@ -36,10 +38,12 @@
<para>Subversion路径授权中,用户对象(用户/别名/组)显然是最重要的基本单位,
每一条授权策略都包含一个用户对象。那么我们第一个迭代就实现用户对象:
- User类,Alias类,Group类。</para>
+ <classname>User</classname> 类,<classname>Alias</classname> 类,
+ <classname>Group</classname> 类。</para>
- <para>假设svnauthz的 User, Alias, Group 类已经完成,我们期望他们实现的功能是什么呢?
- 于是在纸上写下假想任务目标(模拟python交互式命令行):</para>
+ <para>假设 <package>svnauthz</package> 的 <classname>User</classname>,
+ <classname>Alias</classname>, <classname>Group</classname> 类已经完成,
+ 我们期望他们实现的功能是什么呢?于是在纸上写下假想任务目标(模拟python交互式命令行):</para>
<programlisting>
>>> <emphasis>from svnauthz import User, Group, Alias</emphasis>
@@ -125,7 +129,7 @@
<sect3 id="psm.tdd.iter1.unittest.pass">
<title>编写模组,使测试用例通过</title>
- <para>之前执行测试用例失败,报告:找不到 svnauthz 模组。因为模组还没有创建,当然找不到了。
+ <para>之前执行测试用例失败,报告:找不到 <classname>svnauthz</classname> 模组。因为模组还没有创建,当然找不到了。
于是创建一个空的模组文件 <filename>svnauthz.py</filename>。</para>
<screen>
@@ -147,10 +151,11 @@
...
</screen>
- <para>太棒了,我们前进了一步,因为失败的原因已经不同了。错误报告说:User类未定义。
- 于是我们写一些代码,让测试用例通过。</para>
+ <para>太棒了,我们前进了一步,因为失败的原因已经不同了。错误报告说:
+ <classname>User</classname>类未定义。于是我们写一些代码,
+ 让测试用例通过。</para>
- <para>svnauthz.py第一个版本的代码如下:</para>
+ <para><filename>svnauthz.py</filename> 第一个版本的代码如下:</para>
<programlisting><![CDATA[
1 #!/usr/bin/env python
@@ -193,25 +198,25 @@
...
</screen>
- <para>好的,我们已经有一个测试用例(testUser)通过了!其他的测试用例呢?
- 先把他们注释掉,以便提前感受一下完全通过测试的滋味。</para>
+ <para>好的,我们已经有一个测试用例(<classname>testUser</classname>)通过了!
+ 其他的测试用例呢?先把他们注释掉,以便提前感受一下完全通过测试的滋味。</para>
<para>注意:我所说的注释掉不是删除代码,也不是把每一行变为注释,
而是非常简单的将暂不考虑的测试用例改名。</para>
<itemizedlist>
<listitem>
- <para>将 def testAlias(self) 改为 def _testAlias(self)</para>
+ <para>将 <code>def testAlias(self)</code> 改为 <code>def _testAlias(self)</code></para>
</listitem>
<listitem>
- <para>将 def testGroup(self) 改为 def _testGroup(self)</para>
+ <para>将 <code>def testGroup(self)</code> 改为 <code>def _testGroup(self)</code></para>
</listitem>
</itemizedlist>
<note>
- <para>注:只要不是以 test 开头都好。</para>
+ <para>注:只要不是以 <literal>test</literal> 开头都好。</para>
</note>
<para>再次执行测试用例,太棒了完全通过!</para>
@@ -232,8 +237,9 @@
<sect3 id="psm.tdd.iter1.code.coverage">
<title>完善测试用例</title>
- <para>检查代码覆盖度,在Python下有coverage包可用。用easy_install安装之后,
- 就可以使用coverage命令了。</para>
+ <para>检查代码覆盖度,在 Python 下有 <package>coverage</package> 包可用。
+ 用 <command>easy_install</command> 安装之后,
+ 就可以使用 <command>coverage</command> 命令了。</para>
<screen>
$ <emphasis>coverage -x test_svnauthz.py</emphasis>
@@ -250,18 +256,19 @@
svnauthz 8 7 87% 15
</screen>
- <para>哦,看来我们离完美还是差了一点。从coverage的输出中可以看出,
- 我们的测试用例并没有对svnauthz.py的代码测试完全:第15行没有测试到。
- 也就是用空的用户名创建User对象,应该抛出异常。</para>
+ <para>哦,看来我们离完美还是差了一点。从 <command>coverage</command>
+ 的输出中可以看出,我们的测试用例并没有对 <filename>svnauthz.py</filename>
+ 的代码测试完全:第15行没有测试到。也就是用<emphasis>空的用户名</emphasis>创建
+ <classname>User</classname> 对象,应该抛出异常。</para>
- <para>我们在testUser用例的最后补充一条断言:</para>
+ <para>我们在 <methodname>testUser</methodname> 用例的最后补充一条断言:</para>
<programlisting>
def testUser(self):
user1 = User('Tom')
self.assert_(str(user1) == 'Tom')
- self.assertRaises(Exception, User, " ")
- </programlisting>
+ <emphasis>self.assertRaises(Exception, User, " ")</emphasis>
+</programlisting>
<para>再次检查一下测试用例对代码的覆盖度。哇,100% 通过!</para>
@@ -282,10 +289,11 @@
<!-- =============================================================== -->
<sect3 id="psm.tdd.iter1.nosetests">
- <title>用例管理和nosetests</title>
+ <title>用例管理和 nosetests</title>
<para>目前来讲,代码和测试用例共存于同一个目录。我们重构一下,将模组代码放在
- src目录,将测试用例放在 tests 目录。</para>
+ <filename>src</filename> 目录,将测试用例放在 <filename>tests</filename>
+ 目录。</para>
<para>执行测试用例:</para>
@@ -297,7 +305,8 @@
ImportError: No module named svnauthz
</screen>
- <para>在 test_svnauthz.py 文件头增加如下语句,设置Python模组查询路径:</para>
+ <para>在 <filename>test_svnauthz.py</filename> 文件头增加如下语句,
+ 设置 Python 模组查询路径:</para>
<programlisting>
import sys
@@ -306,12 +315,13 @@
<para>测试用例又可以成功执行了。</para>
- <para>tests目录下如果有多个测试用例文件,难道要一个一个去调用么?或者用
- unittest.TestSuite去组织测试用例?其实不用这么麻烦,nosetests
+ <para>目录 <filename>tests</filename> 下如果有多个测试用例文件,
+ 难道要一个一个去调用么?或者用 <classname>unittest.TestSuite</classname>
+ 去组织测试用例?其实不用这么麻烦,<application>nosetests</application>
可以自动发现目录下的测试用例,并执行。</para>
- <para>鼻子测试(nosetests)是一个主动发现测试用例的unittest扩展。
- 可以用easy_install 来安装:</para>
+ <para>鼻子测试(<application>nosetests</application>)是一个主动发现测试用例的
+ unittest 扩展。可以用 <command>easy_install</command> 来安装:</para>
<screen>
$ <emphasis>easy_install nose</emphasis>
@@ -346,15 +356,18 @@
<sect2 id="psm.tdd.continued">
<title>持续迭代</title>
- <para>持续迭代,完成User, Group, Alias, Rules, Module, Repos, SvnAuthz等模组。</para>
+ <para>持续迭代,完成 <classname>User</classname>, <classname>Group</classname>,
+ <classname>Alias</classname>, <classname>Rules</classname>,
+ <classname>Module</classname>, <classname>Repos</classname>,
+ <classname>SvnAuthz</classname> 等模组。</para>
</sect2>
<!-- ================================================================= -->
<sect2 id="psm.tdd.final">
- <title>最终完成的svnauthz</title>
+ <title>最终完成的 svnauthz</title>
- <para>在Python交互模式下测试svnauthz模组:</para>
+ <para>在 Python 交互模式下测试 <classname>svnauthz</classname> 模组:</para>
<screen>
>>> <emphasis>buff = '''# admin: / = administrator</emphasis>
@@ -395,7 +408,7 @@
['@group1 = r', 'user3 = rw', '$authenticated = ', '&admin = rw']
</screen>
- <para>现在是时候给 svnauthz 套上一个华丽一点的外衣了。</para>
+ <para>现在是时候给 <classname>svnauthz</classname> 套上一个华丽一点的外衣了。</para>
</sect2>
已修改: trunk/doc/agile_python/ch03-pylons.xml
===================================================================
--- trunk/doc/agile_python/ch03-pylons.xml 2008-09-12 10:35:00 UTC (rev 91)
+++ trunk/doc/agile_python/ch03-pylons.xml 2008-09-12 15:20:13 UTC (rev 92)
@@ -8,25 +8,38 @@
<sect1 id="psm.pylons">
<title>华丽外衣——Pylons造</title>
- <para>在接触Pylons和其他MVC框架之前,对Pythons的Web编程一直感到比较恐惧,
- 因为看过MoinMoin的代码,要为每一种协议(CGI, FastCGI, mod_python,
- WSGI)写相应的处理代码,实在是麻烦透顶。还好有了Pylons等Web编程框架,
- 为我们屏蔽掉协议一层的复杂度。</para>
+ <para>在接触 Pylons 和其他 MVC 框架之前,对 Python 的 Web 编程一直感到比较恐惧,
+ 因为看过 <application>MoinMoin</application> 的代码,
+ 要为每一种协议(CGI, FastCGI, mod_python, WSGI)写相应的处理代码,
+ 实在是麻烦透顶。还好有了Pylons等Web编程框架,为我们屏蔽了协议一层的复杂度。</para>
- <para>Pylons实现了MVC架构,在使用习惯上和ROR非常类似,因此从学习成本上考虑,
- 我选择了Pylons。</para>
+ <para>Pylons 实现了 MVC 架构,在使用习惯上和 ROR 非常类似,因此从学习成本上考虑,
+ 我选择了 Pylons。</para>
<!-- ================================================================= -->
<sect2 id="psm.pylons.basic">
- <title>建立Web应用框架</title>
+ <title>建立 Web 应用框架</title>
- <para>我们的应用定名为pySvnManager。建立同名的Pylons框架:</para>
+ <para>我们的应用定名为 pySvnManager。建立同名的 Pylons 框架:</para>
<screen>
$ <emphasis>paster create -t pylons pySvnManager</emphasis>
+Selected and implied templates:
+Pylons#pylons Pylons application template
+
+Variables:
+egg: pySvnManager
+package: pysvnmanager
+project: pySvnManager
+Enter template_engine (mako/genshi/jinja/etc: Template language) ['mako']:
+Enter sqlalchemy (True/False: Include SQLAlchemy 0.4 configuration) [False]:
+Creating template pylons
+Creating directory ./pySvnManager
+…
$ <emphasis>cd pySvnManager</emphasis>
$ <emphasis>ls -F</emphasis>
-development.ini docs/ MANIFEST.in pysvnmanager/ pySvnManager.egg-info/ README.txt setup.cfg setup.py test.ini
+development.ini ez_setup.py pysvnmanager/ README.txt setup.py
+docs/ MANIFEST.in pySvnManager.egg-info/ setup.cfg test.ini
</screen>
<para>启动Web应用:</para>
@@ -35,18 +48,20 @@
$ <emphasis>paster serve --reload development.ini</emphasis>
Starting subprocess with file monitor
Starting server in PID 817.
-serving on 0.0.0.0:5000 view at http://127.0.0.1:5000
+serving on http://127.0.0.1:5000
</screen>
<para>用浏览器访问 http://127.0.0.1:5000 会看到一个网页。这个网页实际上调用的是
- public/index.html 文件。如果删除该文件,则浏览器显示404错误(网页未找到)。</para>
+ <filename>public/index.html</filename> 文件。如果删除该文件,则浏览器显示
+ 404错误(网页未找到)。</para>
<!-- =============================================================== -->
<sect3 id="psm.pylons.basic.controller">
<title>理解控制器</title>
- <para>下面用命令创建控制器check,会产生两个文件,一个是控制器文件本身:
- controllers/check.py,另外一个是单元测试文件:tests/functional/test_check.py。</para>
+ <para>下面用命令创建控制器 check,会产生两个文件,一个是控制器文件本身:
+ <filename>controllers/check.py</filename>,另外一个是单元测试文件:
+ <filename>tests/functional/test_check.py</filename>。</para>
<screen>
$ <emphasis>paster controller check</emphasis>
@@ -55,20 +70,20 @@
</screen>
<para>用浏览器访问URL:http://127.0.0.1:5000/check/ 会看到Hello World。
- 我们追根溯源,会看到controllers/check.py中的代码:</para>
+ 我们追根溯源,会看到 <filename>controllers/check.py</filename> 中的代码:</para>
- <screen>
+ <programlisting><![CDATA[
class CheckController(BaseController):
def index(self):
return 'Hello World'
-</screen>
+]]></programlisting>
- <para>哦,原理如此。Pylons已经将URL到代码的映射搞定!就是将浏览器对URL
+ <para>哦,原理如此。Pylons 已经将 URL到代码的映射搞定!就是将浏览器对 URL
的访问映射到控制器代码,再由控制器处理后将结果显示给浏览器。
控制器调用实现逻辑(即Model),然后把从Model获取的结果填充到模板(View)中,
- 于是MVC便实现了逻辑和展现分离。Pylons框架实现的将URL映射到控制器代码,
- 和Windows下VC/Delphi等GUI编程中将事件(鼠标、按钮等)映射到对应的代码是多么的近似。</para>
+ 于是 MVC 便实现了逻辑和展现分离。Pylons 框架实现的将URL映射到控制器代码,
+ 和 Windows 下 VC/Delphi 等GUI编程中将事件(鼠标、按钮等)映射到对应的代码是多么的近似。</para>
</sect3>
@@ -76,21 +91,27 @@
<sect3 id="psm.pylons.basic.routing">
<title>修改控制器映射</title>
- <para>还记得我们已经删除了public/index.html文件么?我们现在通过修改控制器映射,
- 将Web应用的缺省首页指向我们新建立的controller。
- 要修改的文件就是: config/routing.py</para>
+ <para>还记得我们已经删除了 <filename>public/index.html</filename> 文件么?
+ 我们现在通过修改控制器映射,将 Web 应用的缺省首页指向我们新建立的 controller。
+ 要修改的文件就是: <filename>config/routing.py</filename></para>
- <screen>
-20 map.connect('', controller='check', action='index')
-21 map.connect(':controller/:action/:id')
-22 map.connect('*url', controller='template', action='view')
-</screen>
+ <programlisting>
+18 map.connect('/error/{action}', controller='error')
+19 map.connect('/error/{action}/{id}', controller='error')
+20
+21 # CUSTOM ROUTES HERE
+22 <emphasis>map.connect('/', controller='check', action='index')</emphasis>
+23
+24 <emphasis>map.connect('/{controller}')</emphasis>
+25 map.connect('/{controller}/{action}')
+26 map.connect('/{controller}/{action}/{id}')
+</programlisting>
- <para>第20行是我们新增的,告诉Pylons,将缺省的主页定位到名为check的控制器的
- index方法(动作)。</para>
+ <para>第22行是我们新增的,告诉Pylons,将缺省的主页定位到名为 check 的控制器的
+ <methodname>index</methodname> 方法(动作)。</para>
- <para>我们打开浏览器访问 http://127.0.0.1:5000/ 会自动定位到
- http://127.0.0.1:5000/check/index 。</para>
+ <para>我们打开浏览器访问 <uri>http://127.0.0.1:5000/</uri> 会自动定位到
+ <uri>http://127.0.0.1:5000/check/index</uri> 。</para>
</sect3>
@@ -98,28 +119,35 @@
<sect3 id="psm.pylons.basic.model">
<title>加入模组和单元测试</title>
- <para>把我们已经开发完毕的svnauthz模组及其单元测试放到pySvnManager的代码树中,
- 因为svnauthz和pySvnManager的耦合很紧,没有必要单独维护svnauthz模组。</para>
+ <para>把我们已经开发完毕的 <package>svnauthz</package> 模组及其单元测试放到
+ <package>pySvnManager</package> 的代码树中,因为 <classname>svnauthz</classname>
+ 和 <package>pySvnManager</package> 的耦合很紧,没有必要单独维护
+ <package>svnauthz</package> 模组。</para>
- <para>pySvnManager/model 目录是放置模组的地方,将svnauthz的模组放在该目录下。</para>
+ <para><filename>pySvnManager/model</filename> 目录是放置模组的地方,
+ 将 <package>svnauthz</package> 的模组放在该目录下。</para>
- <para>至于单元测试用例,则应该拷贝到pysvnmanager/tests 目录下。该目录下有文件
- test_models.py,就是用于测试模组的。我们先参考 test_models.py
- 文件的格式改造我们原来的模组测试用例test_svnauthz.py,之后再覆盖掉
- test_models.py 文件。新的模组单元测试框架形如:</para>
+ <para>至于单元测试用例,则应该拷贝到 <filename>pysvnmanager/tests</filename>
+ 目录下。该目录下有文件 <filename>test_models.py</filename>,就是用于测试模组的。
+ 我们可以用 <filename>test_svnauthz.py</filename> 覆盖
+ 空文件 <filename>test_models.py</filename> ,并在该文件中设置 Python 包含路径,
+ 以便能成功包含要测试的模组:</para>
- <screen>
+ <programlisting>
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
-3 from pysvnmanager.tests import *
-4 from pysvnmanager import model
-5 from pysvnmanager.model.svnauthz import *
-</screen>
+…
+20 import os
+21 import sys
+22 sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+23
+24 from pysvnmanager.tests import *
+25 from pysvnmanager import model
+26 from pysvnmanager.model.svnauthz import *
+</programlisting>
- <para>其中第五行是新增的。</para>
+ <para>实验一下 <command>nosetests</command> 是否依然可靠运行。</para>
- <para>实验一下nosetests是否依然可靠运行。</para>
-
<screen>
$ <emphasis>nosetests</emphasis>
.............
@@ -139,18 +167,18 @@
<sidebar>
<figure id="psm.pylons.controller.check.fig1">
- <title>控制器check的MVC框架示意图</title>
+ <title>控制器 check 的 MVC 框架示意图</title>
<graphic fileref="images/check_controller.png"/>
</figure>
</sidebar>
<orderedlist>
<listitem>
- <para>路由:用户访问URL或提交表单,由Pylons负责将请求路由至控制器中的同名方法;</para>
+ <para>路由:用户访问URL或提交表单,由 Pylons 负责将请求路由至控制器中的同名方法;</para>
</listitem>
<listitem>
- <para>调用模组:控制器访问模组svnauthz的相关调用,调用结果返回给控制器;</para>
+ <para>调用模组:控制器访问模组 <package>svnauthz</package> 的相关调用,调用结果返回给控制器;</para>
</listitem>
<listitem>
@@ -172,16 +200,17 @@
<sect4 id="psm.pylons.user.to.controller">
<title>控制器获取用户请求</title>
- <para>无论用户使用POST或者GET方式传递请求,都可以用request.params获取。</para>
+ <para>无论用户使用POST或者GET方式传递请求,都可以用
+ <varname>request.params</varname> 获取。</para>
- <screen>
+ <programlisting><![CDATA[
d = request.params # request.params 是包含用户传参的dict
if d.get('userinput') == 'manual':
username = d.get('username') # 从文本框获取用户手工输入的用户名
else:
username = d.get('userselector') # 从下拉框选择的用户名
-</screen>
+]]></programlisting>
</sect4>
@@ -189,12 +218,12 @@
<sect4 id="psm.pylons.controller.to.template">
<title>控制器向视图模板传参</title>
- <screen>
-c.access_map_msg ="<pre>"
+ <programlisting><![CDATA[
+c.access_map_msg ="<pre>"
c.access_map_msg+="\n\n".join(self.authz.get_access_map_msgs(username, repos))
-c.access_map_msg+="</pre>"
+c.access_map_msg+="</pre>"
return render('/check/index.mako')
-</screen>
+]]></programlisting>
</sect4>
@@ -203,16 +232,16 @@
<sect4 id="psm.pylons.template.var">
<title>视图模板用参数填充</title>
- <screen>
-<input type="submit" name="submit" value="提交">
+ <programlisting><![CDATA[
+<input type="submit" name="submit" value="提交">
${h.end_form()}
-<hr>
+<hr>
${c.access_right_msg}
-<pre>
+<pre>
${c.access_map_msg}
-</pre>
-</screen>
+</pre>
+]]></programlisting>
</sect4>
@@ -280,8 +309,8 @@
不过是Python语言的。模板文件的主体依旧是HTML,可以在模板中用“<% %>”
语法嵌入Python代码。例如:</para>
- <screen>
-<%
+ <programlisting><![CDATA[
+<%
userlist = [[u'请选择...', '...'],
[u'所有用户(含匿名)', '*'],
[u'注册用户', '$authenticated'],
@@ -291,7 +320,7 @@
continue
if i[0] == '@':
userlist.append([u'团队:'+i[1:], i])
- elif i[0] == '&':
+ elif i[0] == '&':
userlist.append([u'别名:'+i[1:], i])
else:
userlist.append([i, i])
@@ -305,19 +334,19 @@
pathlist = [[u'所有路径...', '*'],]
for i in c.pathlist:
pathlist.append([i, i])
-%>
-</screen>
+%>
+]]></programlisting>
<para>可以用“${expression}”将页面Python代码的或者Controller
传递的变量/表达式的值直接嵌入到模板中输出。例如:</para>
- <screen>
-<input type="radio" name="reposinput" value="select"
- ${c.checked_reposinput_select}> 选择代码库
- <select name="reposselector" size="0" onFocus="select_repos(this.form)">
+ <programlisting><![CDATA[
+<input type="radio" name="reposinput" value="select"
+ ${c.checked_reposinput_select}> 选择代码库
+ <select name="reposselector" size="0" onFocus="select_repos(this.form)">
${h.options_for_select(reposlist, c.selected_repos)}
- </select>
-</screen>
+ </select>
+]]></programlisting>
</sect3>
@@ -325,7 +354,7 @@
<sect3 id="psm.pylons.controller.method.index">
<title>控制器的index方法</title>
- <screen>
+ <programlisting><![CDATA[
class CheckController(BaseController):
def __init__(self):
@@ -338,7 +367,7 @@
def index(self):
return render('/check/index.mako')
-</screen>
+]]></programlisting>
</sect3>
@@ -420,13 +449,38 @@
${h.javascript_include_tag(builtins=True)}
]]></screen>
- <para>实际上会在页面中产生下面两个JavaScrip包含语句:</para>
+ <para>实际上会在页面中产生下面两个JavaScrip包含语句:</para>
- <screen><![CDATA[
+ <screen><![CDATA[
<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/scriptaculous.js" type="text/javascript"></script>
]]></screen>
+ <sidebar>
+ <para>最新版本的 Pylons 使用 0.6 版本的 <package>WebHelpers</package>,
+ 不建议使用 <package>webhelpers.rails</package>,甚至在未来版本去掉
+ <package>webhelpers.rails</package>。也不再自动 import
+ <package>webhelpers.rails</package>。对于要用到的 webhelpers 方法,
+ 需要显示的声明。参见文件 <filename>lib/helpers.py</filename>。</para>
+
+ <programlisting>
+from routes import url_for, redirect_to
+from webhelpers.html import escape, HTML, literal, url_escape
+from webhelpers.html.tags import *
+from webhelpers.rails.prototype import link_to_remote, form_remote_tag
+from webhelpers.rails.scriptaculous import visual_effect
+from webhelpers.rails.asset_tag import javascript_include_tag, stylesheet_link_tag
+</programlisting>
+
+ <para>相关的 prototype 和 scriptaculous JavaScript 脚本,在新版的 Pylons
+ 中也不提供,需要从相关站点下载,复制到 <filename>public/javascripts/</filename>
+ 目录下。</para>
+
+ <para>建议逐步将 webhelpers.rails 调用替换。建议使用 Fork JavaScript 框架
+ 取代 Prototype 的 JavaScript 框架。</para>
+
+ </sidebar>
+
</sect3>
已修改: trunk/doc/agile_python/index.xml
===================================================================
--- trunk/doc/agile_python/index.xml 2008-09-12 10:35:00 UTC (rev 91)
+++ trunk/doc/agile_python/index.xml 2008-09-12 15:20:13 UTC (rev 92)
@@ -21,15 +21,24 @@
<articleinfo>
<title>敏捷 Web 开发实践</title>
<subtitle>—— pySvnManager 项目实战</subtitle>
- <author><firstname><ulink url="http://www.ossxp.com"/>www.ossxp.com</firstname></author>
+ <author><firstname><ulink url="http://www.ossxp.com"/></firstname></author>
<affiliation>
<orgname>&orgname;</orgname>
- <address><link><uri>http://www.ossxp.com</uri></link></address>
+ <address><email>worldhello.net AT gmail.com</email></address>
</affiliation>
<revhistory>
<revision>
+ <revnumber>0.2</revnumber>
+ <date>2008/09/12</date>
+ <authorinitials>&author;</authorinitials>
+ <revremark>随 Pylons 升级为 0.9.7,pySvnManager 升级为 0.3。修改 WebHelpers 以及 routing 等相关内容。</revremark>
+ </revision>
+ </revhistory>
+
+ <revhistory>
+ <revision>
<revnumber>0.1</revnumber>
<date>2008/07/20</date>
<authorinitials>&author;</authorinitials>
@@ -38,10 +47,11 @@
</revhistory>
<abstract>
- <para>敏捷也许就是保障项目成功的“银弹”。笔者通过最近完成的一个小项目切身体验了一下
- Python 语言在Web敏捷开发上的强大力量,愿与您共享。</para>
+ <para><emphasis>敏捷</emphasis>也许就是保障项目成功的“银弹”。
+ 笔者通过最近完成的一个小项目切身体验了一下 Python 语言在
+ Web 敏捷开发上的强大力量,愿与您共享。</para>
- <para>(版本号: 0.1.&doc.revision;,最后更新时间: &doc.lastchange;)</para>
+ <para>(版本号: 0.2.&doc.revision;,最后更新时间: &doc.lastchange;)</para>
</abstract>
</articleinfo>
_______________________________________________
Svn mailing list
S...@list.worldhello.net
http://www.worldhello.net/mailman/listinfo/svn