Differences between revisions 13 and 14
Revision 13 as of 2008-11-13 07:00:02
Size: 8542
Editor: ZoomQuiet
Comment:
Revision 14 as of 2008-11-14 15:25:05
Size: 16081
Editor: ZoomQuiet
Comment:
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
||'''status'''|| 校对 || ZoomQuiet|| 完成度:25%|| ||'''status'''|| 校对 || ZoomQuiet|| 完成度:85%||
Line 11: Line 11:
= PCS304 Web应用框架纵览 = = PCS304 Python Web应用框架综论 =
Line 14: Line 14:

== 为啥介多框架?! ==

还有人站着说话不腰痛的分析"[http://xlp223.yculblog.com/post.1634226.html 为何有如此多的python web 框架?]"
 * Web ~ 互联网的泛称;
 * Web应用 ~ 基于互联网的应用简称;
 * 框架 ~ Framework,是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架;(前者是从应用方面而后者是从目的方面给出的定义)
  * 框架是可复用的设计构件库
  * 框架就是某种应用的半成品
  * 框架是一个可复用设计,由一组抽象类及其实例间协作关系来表达的
  * 框架是在一个给定的问题领域内,一个应用程序的一部分设计与实现
  * 框架是为解决代码复用问题的一个最靠谱的尝试
  * 框架是,,,
 * Python Web应用框架 ~ 由Python实现的面向互联网应用开发的框架!
  * 对于开发者,就是一堆模块和使用这些模块的文档,基于这些框架,可以快速的完成有很高品质的互联网应用系统;而不用要求开发者有多么高深的相关领域经验;
  * 可以说,框架就是游戏里的组合技,掌握了,就立即可以从菜鸟变成高手!
 * 不过,在Python 世界,仅仅针对互联网应用的专门框架,就有不下20种!以至有人专门研究:"[http://xlp223.yculblog.com/post.1634226.html 为何有如此多的Python Web实用框架?]"
Line 22: Line 31:
 * E文出处:[http://bitworking.org/news/Why_so_many_Python_web_frameworks Why so many Python web frameworks?]  * 文出处:[http://bitworking.org/news/Why_so_many_Python_web_frameworks Why so many Python web frameworks?]
Line 27: Line 36:

{{{注意:
上述文章中,作者为了展示任何人可以通过Python快速创建自个儿的Web应用框架,
当场使用 9个文件创建并运行了一个含有足够功能的框架!
详细请参看本章最后小结部分
}}}
文章中,作者为了展示任何人可以通过Python快速创建自个儿的Web应用框架,
当场使用 8个文件(6个Python脚本,一个页面模板文件,一个服务器脚本)创建并运行了一个含有足够功能的应用框架! 
以些来回答了'''为何有如此多Python Web实用框架?''':
 * 因为,`实现一个忒简单了!`
Line 157: Line 164:
  1. 初始化数据{{{   1. 通过交互环境,初始化数据{{{
Line 175: Line 182:
  1. 通过 cgi 在各种Web服务器中运行{{{
#!/usr/bin/python2.4
import manage
manage.run()
}}}
   * 也可以部署前述 main.cgi 到各种Web服务器中运行发布应用
Line 182: Line 185:
  * 通过 SQLAlchemy 进行对象化高效数据库操作   * 通过 SQLAlchemy 进行高效对象化数据库操作
Line 184: Line 187:
  * 使用 WSGI(Web 服务器网关接口)模式运行   * 使用 WSGI(Web 服务器网关接口)模式运行
Line 187: Line 190:
  * 可对URL进行映射管理
  * 使用 Kid 模板系统,高效输出数据
  * 可对URL进行映射管理
  * 使用 Kid 模板系统,高效输出数据
Line 191: Line 194:
  * 全功能Web应用框架!
是一个完备的,全功能Web应用框架!通过极少的配置和开发,就可以完成一个动态数据展示页面!
Line 194: Line 198:

== 由来 ==
正是因为使用Python 能够轻易的将各种即有模块组合出一个Web应用框架来;

所以,不象其它语言世界,仅仅有唯一或是极少数Web应用框架,,,

在Python 世界,有太多太多的应用框架,,,以致于大家被选择哪个所深深困惑! 即怕选择错框架,带来开发的麻烦;又怕一但选定了框架,将来享受不到其它框架更加美妙的特性,,,患得患失中,痛苦渡日;-)

这里行者们根据一些使用过的框架,综合考虑各种因素,大致的给出比较靠谱的Python Web应用框架理解来,以便帮助大家面对异常丰厚的Python Web应用框架,如何保持"平常心",正确对待各种框架;

=== 回顾 ===
按照笔者接触到框架的时间顺序来排列大致是这样的:
 1. Zope
 1. Twisted
 1. Snakelets
 1. CherryPy
 1. Quixote
 1. Karrigell
 1. WukooPy
 1. web.py
 1. Django
 1. TurboGears
 1. Pylons
 1. Eurasia
 1. Web2py
 1. Uliweb
 
 这里没有给出详细的开发社区情况,以及笔者体验框架的详细日期和情景,只是大致的列出先后接触/了解/应用框架的顺序;以此为基础,分享一点,对Python Web应用框架的体验:
 * 各个框架都有鲜明的个性! 关注的问题领域各不相同;
 * 各个框架都有明确的社区, 有专门的开发团队来维护~当然有的甚至于就是一个开发人员;
 * 各个框架都能在不同程度上和其它框架/模块联用(这是Python 的胶水特质决定的);
 
=== 分类 ===
进一步的,根据前述"Joe Gregorio的超级框架",可以明确一个功能完备的Web应用框架,至少应该包含以下方面的功能支持:
 1. 服务发布
 1. URL分发
 1. 模板支持
 1. 数据库处理

各种框架一般前三个方面都支持的不错,根据对第4个方面的态度,那么可以大致将所有Python Web应用框架分成以下几类:

 平台性框架::
 这类框架,认为框架不应该依赖数据库,是关注应用的高效构建和运行平台的;Zope和Twisted属于这类,都是非常深遂的框架!
  * Zope 开发时间长,引发的影响大,甚至于有人认为:"未来互联网就是Zope";开创了一系列Web应用开发的新技术和理念,形成了宏大的社区和模块树; 虽然学习曲线实在太陡,但是过来人都说:"只要是作Web应用开发,学到底就会发现,其实一切都在Zope 中实现过了!"
  * Twisted 也是老牌社区的作品,关注网络应用底层支持,支持几乎所有网络协议,关注企业级的网络服务构建;只是缺少立等可取的应用框架,一切都得用Twisted 去现实,算是提供了成套工具的钻石级工具箱!
  
 轻小型框架::
 这类框架,认为数据库不是应用的必要因素,是关注友好快速的简单任务型网站开发的;CherryPy/Quixote/Karrigell/web.py等等都属于这类框架,标志特性是没有内置的数据库(类似MySQL 的关系型主流数据库)支持模块;
  * 突出的共同特色有:
   * 配置简便
   * 模板系统简单轻便,或是可以自由使用外部模板系统
   * 调试相对方便,有的甚至有专门的问题回溯机制
  
 一站式框架::
 这类框架,认为数据库是应用的重要因素,是关注如何仅基于本身就可以快速独立的实现一个功能型网站;Django/TurboGears/Eurasia/UliWeb等等都属于这类框架;
  * 突出的共同特色有:
   * 有内置的ORM模块支持数据库的对象化操作;
   * 有内置的事务性功能支持(比如说登录认证);
   * 有高级的模板系统,支持复杂的页面组合,有的甚至于有内置的Ajax 页面动态效果支持;

=== 选择 ===
好的,即使可以快速理解现有的Py框架,但是也无法保证永远不再出现新好框架;所以,如何理性的靠谱的为自个儿的应用选择一个合适的框架?

 笔者推荐一个思路::
  根据项目面对的问题域特性来进行评定,取舍!
  * 核心问题:
{{{
A. 项目是否需要长期运营?
B. 项目是否足够复杂多变?
}}}
  * 就可以根据以下的判决矩阵进行决策:
||<-2>问题状态|| 框架选择||
|| A || B || ` ` ||
|| Y || Y ||平台型框架最佳 ||
|| Y || N ||轻小性框架即可,平台型框架最佳 ||
|| N || Y ||一站式架最佳 ||
|| N || N ||轻小性框架最佳 ||
  * 是综合考虑到以下因素,而总结的决策矩阵:
   1. 长期运营时,关键成本在维护,这要求框架足够稳定和容易谅解;
   1. 业务复杂时,关键成本在开发,这要求框架有足够的内置支持,以便减少开发投入;
   1. 平台型框架都有浑厚的积累,可以满足一切要求,但是需要一定的学习成本,以便恰当的运用好这些特性;
   1. 轻小型框架由于代码精悍,一般都有很好的负载能力,而且代码简洁,容易定制和扩展;
   1. 一站式框架,又分两类:
    * 一则"All in one 式"的,任何方面功能都是自行开发内置包含的;
    * 二则"Mix-in 式"的,多数方面功能是直接包含外部模块来配合完成的;
    * "All in one 式"的胜在内部契合严密运行效率高!但是,一但有问题就非常难以清查,而且一般很难作到平滑的版本兼容;
    * "Mix-in 式"的胜在选择自由,可以使用各种类似的自己熟悉的功能组件来替代默认的,学习成本小,而且各个组件可以单独升级,版本兼容危机小;但是,由于要兼顾各种组件接口,隐含的问题要多些;
   1. 前端模板系统,也分两类:
    * 一则解释型的,需要动态加载Python 运行渲染出结果再输出;
    * 二则编译型的,事先编译成可执行中间代码了,输出时可以直接融合入数据;
    * 后者运行效率要高过前者,但是开发时,调试方面就是解释型的比编译型的要直观方便了;
    * 功能网站的运行效率,很大部分就是和模板效率以及数据库处理效率相关!

  

    | +-- 如何来理解各种框架?
    | +-- 框架的框架
    | +-- 轻型框架
    | +-- 一站式框架
    | \-- 模板系统
    +-- 细说(按照历史顺序,选择经典框架来介绍,没有PCS独立章节的,和故事没有直接提及的)
Line 295: Line 396:
创建 by -- ZoomQuiet [[[DateTime(2008-11-13T07:00:02Z)]]] 创建 by -- ZoomQuiet [[[DateTime(2008-11-14T15:25:05Z)]]]

status

校对

ZoomQuiet

完成度:85%

TableOfContents

PCS304 Python Web应用框架综论

  • Web ~ 互联网的泛称;
  • Web应用 ~ 基于互联网的应用简称;
  • 框架 ~ Framework,是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架;(前者是从应用方面而后者是从目的方面给出的定义)
    • 框架是可复用的设计构件库
    • 框架就是某种应用的半成品
    • 框架是一个可复用设计,由一组抽象类及其实例间协作关系来表达的
    • 框架是在一个给定的问题领域内,一个应用程序的一部分设计与实现
    • 框架是为解决代码复用问题的一个最靠谱的尝试
    • 框架是,,,
  • Python Web应用框架 ~ 由Python实现的面向互联网应用开发的框架!
    • 对于开发者,就是一堆模块和使用这些模块的文档,基于这些框架,可以快速的完成有很高品质的互联网应用系统;而不用要求开发者有多么高深的相关领域经验;
    • 可以说,框架就是游戏里的组合技,掌握了,就立即可以从菜鸟变成高手!
  • 不过,在Python 世界,仅仅针对互联网应用的专门框架,就有不下20种!以至有人专门研究:"[http://xlp223.yculblog.com/post.1634226.html 为何有如此多的Python Web实用框架?]"

{{{脚注: 访问地址:http://xlp223.yculblog.com/post.1634226.html 精巧地址:http://tinyurl.com/6yajuo }}}

{{{脚注: 访问地址:http://bitworking.org/news/Why_so_many_Python_web_frameworks 精巧地址:http://tinyurl.com/6kv9j3 }}} 在此文章中,作者为了展示任何人可以通过Python快速创建自个儿的Web应用框架, 当场使用 8个文件(6个Python脚本,一个页面模板文件,一个服务器脚本)创建并运行了一个含有足够功能的应用框架! 以些来回答了为何有如此多的Python Web实用框架?:

  • 因为,实现一个忒简单了!

Joe Gregorio的超级框架

组成
  1. model.py ~ 数据库设计模板脚本

       1 from sqlalchemy import Table, Column, String
       2 import dbconfig
       3 
       4 entry_table = Table('entry', dbconfig.metadata,
       5              Column('id', String(100), primary_key=True),
       6              Column('title', String(100)),
       7              Column('content', String(30000)),
       8              Column('updated', String(20), index=True)
       9          )
    
  2. dbconfig.py ~ 数据库连接配置脚本

       1 from sqlalchemy import *
       2 metadata = BoundMetaData('sqlite:///tutorial.db')
    
  3. manage.py ~ 服务管理脚本

       1 import os, sys
       2 
       3 def create():
       4     from sqlalchemy import Table
       5     import model
       6     for (name, table) in vars(model).iteritems():
       7         if isinstance(table, Table):
       8             table.create()
       9 
      10 def run():
      11     '''使用WSGI模式启动服务
      12     '''
      13     import urls
      14     if os.environ.get("REQUEST_METHOD", ""):
      15         from wsgiref.handlers import BaseCGIHandler
      16         BaseCGIHandler(sys.stdin, sys.stdout, sys.stderr, os.environ).run(urls.urls)
      17     else:
      18         from wsgiref.simple_server import WSGIServer, WSGIRequestHandler
      19         httpd = WSGIServer(('', 8080), WSGIRequestHandler)
      20         httpd.set_app(urls.urls)
      21         print "Serving HTTP on %s port %s ..." % httpd.socket.getsockname()
      22         httpd.serve_forever()
      23 
      24 if __name__ == "__main__":
      25    if 'create' in sys.argv:
      26         create()
      27    if 'run' in sys.argv:
      28         run()
    
  4. main.cgi ~ 服务器运行脚本

    import manage
    manage.run()
  5. urls.py ~ 基于URL的对象选择器

       1 import selector
       2 import view
       3 
       4 urls = selector.Selector()
       5 urls.add('/blog/', GET=view.list)
       6 urls.add('/blog/{id}/', GET=view.member_get)
       7 urls.add('/blog/;create_form', POST=view.create, GET=view.list)
       8 urls.add('/blog/{id}/;edit_form', GET=view.member_get, POST=view.member_update)
    
  6. view.py ~ 基于WSGI应用的多个视图

       1 import robaccia
       2 import model
       3 
       4 def list(environ, start_response):
       5     rows = model.entry_table.select().execute()
       6     return robaccia.render(start_response, 'list.html', locals())
       7 
       8 def member_get(environ, start_response):
       9     id = environ['selector.vars']['id']
      10     row = model.entry_table.select(model.entry_table.c.id==id).execute().fetchone()
      11     return robaccia.render(start_response, 'entry.html', locals())
      12 
      13 def create(environ, start_response):
      14     pass
      15 def create_form(environ, start_response):
      16     pass
      17 def member_edit_form(environ, start_response):
      18     pass
      19 def member_update(environ, start_response):
      20     pass
    
  7. robaccia.py ~ 模板处置脚本

       1 import kid
       2 import os
       3 
       4 extensions = {
       5     'html': 'text/html',
       6     'atom': 'application/atom+xml'
       7 }
       8 
       9 def render(start_response, template_file, vars):
      10     ext = template_file.rsplit(".")
      11     contenttype = "text/html"
      12     if len(ext) > 1 and (ext[1] in extensions):
      13         contenttype = extensions[ext[1]]
      14 
      15     template = kid.Template(file=os.path.join('templates', template_file), **vars)
      16     body = template.serialize(encoding='utf-8')
      17 
      18     start_response("200 OK", [('Content-Type', contenttype)])
      19     return [body]
    
  8. list.html ~ 页面应用模板

    <?xml version="1.0" encoding="utf-8"?>
    <html xmlns:py="http://purl.org/kid/ns#>">
    <head>
     <title>A Robaccia Blog</title> 
     </head>
    <div py:for="row in rows.fetchall()">
    <h2>${row.title}</h2>
    <div>${row.content}</div>
    <p><a href="./${row.id}/">${row.updated}</a></p>
    </div>
    </html>
使用
  1. 创建数据库

    ~$ python manage.py create
  2. 通过交互环境,初始化数据

    ~$ python
    Python 2.4.3 (#2, Apr 27 2006, 14:43:58)
    [GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import model
    >>> i = model.entry_table.insert()
    >>> i.execute(id='first-post', title="Some Title", content="Some pithy text...",  
       updated="2006-09-01T01:00:00Z")
    
    >>> i.execute(id='second-post', title="Moving On", content="Some not so pithy words...",  
       updated="2006-09-01T01:01:00Z")
  3. 独立运行

    ~$ python manage.py run
    Serving HTTP on 0.0.0.0 port 8080 ...
    • 也可以部署前述 main.cgi 到各种Web服务器中运行发布应用
能力

是一个完备的,全功能Web应用框架!通过极少的配置和开发,就可以完成一个动态数据展示页面!

现状

正是因为使用Python 能够轻易的将各种即有模块组合出一个Web应用框架来;

所以,不象其它语言世界,仅仅有唯一或是极少数Web应用框架,,,

在Python 世界,有太多太多的应用框架,以致于大家被选择哪个所深深困惑! 即怕选择错框架,带来开发的麻烦;又怕一但选定了框架,将来享受不到其它框架更加美妙的特性,患得患失中,痛苦渡日;-)

这里行者们根据一些使用过的框架,综合考虑各种因素,大致的给出比较靠谱的Python Web应用框架理解来,以便帮助大家面对异常丰厚的Python Web应用框架,如何保持"平常心",正确对待各种框架;

回顾

按照笔者接触到框架的时间顺序来排列大致是这样的:

  1. Zope
  2. Twisted
  3. Snakelets
  4. CherryPy

  5. Quixote
  6. Karrigell
  7. WukooPy

  8. web.py
  9. Django
  10. TurboGears

  11. Pylons
  12. Eurasia
  13. Web2py
  14. Uliweb 这里没有给出详细的开发社区情况,以及笔者体验框架的详细日期和情景,只是大致的列出先后接触/了解/应用框架的顺序;以此为基础,分享一点,对Python Web应用框架的体验:
  15. 各个框架都有鲜明的个性! 关注的问题领域各不相同;
  16. 各个框架都有明确的社区, 有专门的开发团队来维护~当然有的甚至于就是一个开发人员;
  17. 各个框架都能在不同程度上和其它框架/模块联用(这是Python 的胶水特质决定的);

分类

进一步的,根据前述"Joe Gregorio的超级框架",可以明确一个功能完备的Web应用框架,至少应该包含以下方面的功能支持:

  1. 服务发布
  2. URL分发
  3. 模板支持
  4. 数据库处理

各种框架一般前三个方面都支持的不错,根据对第4个方面的态度,那么可以大致将所有Python Web应用框架分成以下几类:

平台性框架
这类框架,认为框架不应该依赖数据库,是关注应用的高效构建和运行平台的;Zope和Twisted属于这类,都是非常深遂的框架!
  • Zope 开发时间长,引发的影响大,甚至于有人认为:"未来互联网就是Zope";开创了一系列Web应用开发的新技术和理念,形成了宏大的社区和模块树; 虽然学习曲线实在太陡,但是过来人都说:"只要是作Web应用开发,学到底就会发现,其实一切都在Zope 中实现过了!"
  • Twisted 也是老牌社区的作品,关注网络应用底层支持,支持几乎所有网络协议,关注企业级的网络服务构建;只是缺少立等可取的应用框架,一切都得用Twisted 去现实,算是提供了成套工具的钻石级工具箱!
轻小型框架
这类框架,认为数据库不是应用的必要因素,是关注友好快速的简单任务型网站开发的;CherryPy/Quixote/Karrigell/web.py等等都属于这类框架,标志特性是没有内置的数据库(类似MySQL 的关系型主流数据库)支持模块;
  • 突出的共同特色有:
    • 配置简便
    • 模板系统简单轻便,或是可以自由使用外部模板系统
    • 调试相对方便,有的甚至有专门的问题回溯机制
一站式框架
这类框架,认为数据库是应用的重要因素,是关注如何仅基于本身就可以快速独立的实现一个功能型网站;Django/TurboGears/Eurasia/UliWeb等等都属于这类框架;
  • 突出的共同特色有:
    • 有内置的ORM模块支持数据库的对象化操作;
    • 有内置的事务性功能支持(比如说登录认证);
    • 有高级的模板系统,支持复杂的页面组合,有的甚至于有内置的Ajax 页面动态效果支持;

选择

好的,即使可以快速理解现有的Py框架,但是也无法保证永远不再出现新好框架;所以,如何理性的靠谱的为自个儿的应用选择一个合适的框架?

笔者推荐一个思路
  • 根据项目面对的问题域特性来进行评定,取舍!
  • 核心问题:

A. 项目是否需要长期运营?
B. 项目是否足够复杂多变?
  • 就可以根据以下的判决矩阵进行决策:

问题状态

框架选择

A

B

 

Y

Y

平台型框架最佳

Y

N

轻小性框架即可,平台型框架最佳

N

Y

一站式架最佳

N

N

轻小性框架最佳

  • 是综合考虑到以下因素,而总结的决策矩阵:
    1. 长期运营时,关键成本在维护,这要求框架足够稳定和容易谅解;
    2. 业务复杂时,关键成本在开发,这要求框架有足够的内置支持,以便减少开发投入;
    3. 平台型框架都有浑厚的积累,可以满足一切要求,但是需要一定的学习成本,以便恰当的运用好这些特性;
    4. 轻小型框架由于代码精悍,一般都有很好的负载能力,而且代码简洁,容易定制和扩展;
    5. 一站式框架,又分两类:
      • 一则"All in one 式"的,任何方面功能都是自行开发内置包含的;
      • 二则"Mix-in 式"的,多数方面功能是直接包含外部模块来配合完成的;
      • "All in one 式"的胜在内部契合严密运行效率高!但是,一但有问题就非常难以清查,而且一般很难作到平滑的版本兼容;
      • "Mix-in 式"的胜在选择自由,可以使用各种类似的自己熟悉的功能组件来替代默认的,学习成本小,而且各个组件可以单独升级,版本兼容危机小;但是,由于要兼顾各种组件接口,隐含的问题要多些;
    6. 前端模板系统,也分两类:
      • 一则解释型的,需要动态加载Python 运行渲染出结果再输出;
      • 二则编译型的,事先编译成可执行中间代码了,输出时可以直接融合入数据;
      • 后者运行效率要高过前者,但是开发时,调试方面就是解释型的比编译型的要直观方便了;
      • 功能网站的运行效率,很大部分就是和模板效率以及数据库处理效率相关! | +-- 如何来理解各种框架? | +-- 框架的框架 | +-- 轻型框架 | +-- 一站式框架 | \-- 模板系统 +-- 细说(按照历史顺序,选择经典框架来介绍,没有PCS独立章节的,和故事没有直接提及的)

探讨

Eurasia3 前面已经

支持 Mako 的 <%def name=""> <%call expr=""> <% python code %> ${...}

from template import compile, Template

s = '''\
<%def name="test2(a, b)">
 ${caller.test3()} or ${context.get('test3', None)()}

 %if a:
  ${a}
 %elif b:
  ${b}
 %else:
  <%write('hello')%>
 %endif

 %for i in xrange(100):
  ${str(i)}
 %endfor
</%def>

<%def name="test(c, d)">
 <%call expr="test2(1, 2)">
  <%def name="test3()">
   <%
    x = 1
   %>
   hello world! in test3
  </%def>
 </%call>
</%def>
'''

print compile(s)

m = Template(s)
print m.test('aaa', 'bbb')

shelve2 已经在实用了。这个模板会被用在建立 Eurasia3 项目主站上

导读

  • 总体回顾,给出相关阅读和思考指引
  • Zope ~ 超浑厚框架 Jungyong Pan (100%)
  • Quxiote ~ 豆瓣动力核心 ~ QiangningHong(100%)

  • Django~最流行框架快速体验教程 黄毅(100%)
  • Eurasia ~ 关注高性能的原创框架 沈崴(100%)
  • UliWeb ~ 关注平衡感的自制框架 Limodou(100%)

  • 深入探索Python的Web开发 HuangYi(100%)

  • Python Web应用框架纵论 ::
     
        +-- 导论
        |  +-- 现状
        |  \-- 为什么Python 中有这么多框架?
        +-- 分类
        |  +-- 如何来理解各种框架?
        |  +-- 框架的框架
        |  +-- 轻型框架
        |  +-- 一站式框架
        |  \-- 模板系统
        +-- 细说(按照历史顺序,选择经典框架来介绍,没有PCS独立章节的,和故事没有直接提及的)
        |  +-- Zope/Plone (请潘俊勇撰写)
        |  +-- Quixote (请 阿北或是朞其它豆瓣成员 撰写)
        |  +-- Eruasia (请 沈崴 撰写)
        |  +-- Django (HY自写)
        |  \-- UliWeb (请Limodou撰写)
        +-- 选择
        |  +-- 个人
        |  +-- 团队
        |  \-- 企业
        \-- 小结
          \-- 选择的痛苦


反馈

创建 by -- ZoomQuiet [DateTime(2008-11-14T15:25:05Z)]

PageComment2

[:/PageCommentData:PageCommentData]

ObpLovelyPython/PCS304 (last edited 2010-03-01 03:09:51 by ZoomQuiet)