Differences between revisions 9 and 11 (spanning 2 versions)
Revision 9 as of 2008-11-12 08:53:37
Size: 8375
Editor: ZoomQuiet
Comment:
Revision 11 as of 2008-11-13 06:57:45
Size: 8548
Editor: ZoomQuiet
Comment:
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
||'''status'''|| 校对 || ZoomQuiet|| 完成度:15%|| ||'''status'''|| 校对 || ZoomQuiet|| 完成度:25%||
Line 10: Line 10:
Line 13: Line 14:
 概述::
    简洁的介绍知识点的来由

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

还有人站着说话不腰痛的分析"[http://xlp223.yculblog.com/post.1634226.html 为何有如此多的python web 框架?]"
{{{脚注:
访问地址:http://xlp223.yculblog.com/post.1634226.html
精巧地址:http://tinyurl.com/6yajuo
}}}
 * 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
精巧地址:http://tinyurl.com/6kv9j3
}}}

{{{注意:
在上述文章中,作者为了展示任何人可以通过Python快速创建自个儿的Web应用框架,
当场使用 9个文件创建并运行了一个含有足够功能的框架!
详细请参看本章最后的小结部分
}}}

=== Joe Gregorio的超级框架 ===
 组成::
  1. model.py ~ 数据库设计模板脚本{{{#!python
from sqlalchemy import Table, Column, String
import dbconfig

entry_table = Table('entry', dbconfig.metadata,
             Column('id', String(100), primary_key=True),
             Column('title', String(100)),
             Column('content', String(30000)),
             Column('updated', String(20), index=True)
         )
}}}
  1. dbconfig.py ~ 数据库连接配置脚本{{{#!python
from sqlalchemy import *
metadata = BoundMetaData('sqlite:///tutorial.db')
}}}
  1. manage.py ~ 服务管理脚本{{{#!python
import os, sys

def create():
    from sqlalchemy import Table
    import model
    for (name, table) in vars(model).iteritems():
        if isinstance(table, Table):
            table.create()

def run():
    '''使用WSGI模式启动服务
    '''
    import urls
    if os.environ.get("REQUEST_METHOD", ""):
        from wsgiref.handlers import BaseCGIHandler
        BaseCGIHandler(sys.stdin, sys.stdout, sys.stderr, os.environ).run(urls.urls)
    else:
        from wsgiref.simple_server import WSGIServer, WSGIRequestHandler
        httpd = WSGIServer(('', 8080), WSGIRequestHandler)
        httpd.set_app(urls.urls)
        print "Serving HTTP on %s port %s ..." % httpd.socket.getsockname()
        httpd.serve_forever()

if __name__ == "__main__":
   if 'create' in sys.argv:
        create()
   if 'run' in sys.argv:
        run()
}}}
 1. main.cgi ~ 服务器运行脚本{{{
#!/usr/bin/python2.4
import manage
manage.run()
}}}
  1. urls.py ~ 基于URL的对象选择器{{{#!python
import selector
import view

urls = selector.Selector()
urls.add('/blog/', GET=view.list)
urls.add('/blog/{id}/', GET=view.member_get)
urls.add('/blog/;create_form', POST=view.create, GET=view.list)
urls.add('/blog/{id}/;edit_form', GET=view.member_get, POST=view.member_update)
}}}
  1. view.py ~ 基于WSGI应用的多个视图{{{#!python
import robaccia
import model

def list(environ, start_response):
    rows = model.entry_table.select().execute()
    return robaccia.render(start_response, 'list.html', locals())

def member_get(environ, start_response):
    id = environ['selector.vars']['id']
    row = model.entry_table.select(model.entry_table.c.id==id).execute().fetchone()
    return robaccia.render(start_response, 'entry.html', locals())

def create(environ, start_response):
    pass
def create_form(environ, start_response):
    pass
def member_edit_form(environ, start_response):
    pass
def member_update(environ, start_response):
    pass
}}}
  1. robaccia.py ~ 模板处置脚本{{{#!python
import kid
import os

extensions = {
    'html': 'text/html',
    'atom': 'application/atom+xml'
}

def render(start_response, template_file, vars):
    ext = template_file.rsplit(".")
    contenttype = "text/html"
    if len(ext) > 1 and (ext[1] in extensions):
        contenttype = extensions[ext[1]]

    template = kid.Template(file=os.path.join('templates', template_file), **vars)
    body = template.serialize(encoding='utf-8')

    start_response("200 OK", [('Content-Type', contenttype)])
    return [body]
}}}
  1. 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
}}}
  1. 初始化数据{{{
~$ 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")
}}}
  1. 独立运行{{{
~$ python manage.py run
Serving HTTP on 0.0.0.0 port 8080 ...

}}}
  1. 通过 cgi 在各种Web服务器中运行{{{
#!/usr/bin/python2.4
import manage
manage.run()
}}}

 能力::
  * 通过 SQLAlchemy 进行对象化高效数据库操作的
   * SQLAlchemy官方网站 http://www.sqlalchemy.org/
  * 使用 WSGI(Web 服务器网关接口)模式运行的
   * WSGI官方网站: http://www.wsgi.org/wsgi/What_is_WSGI
   * 精巧地址: http://bit.ly/3IkgU4
  * 可对URL进行映射管理的
  * 使用 Kid 模板系统,高效输出数据的
   * Kid官方网站 http://www.kid-templating.org/
   * 精巧地址: http://bit.ly/2YDxPd
  * 全功能Web应用框架!

== 现状 ==

== 由来 ==


== 探讨 ==
 
Eurasia3 前面已经
 * 用 895 行单文件实现了 ZODB
  * 下载地址: http://code.google.com/p/eurasia/source/browse/trunk/Eurasia/shelve2.py
  * 精巧地址: http://bit.ly/1yzuqZ
 * 这次更过分了, Mako 只有 377 行。把类似于 Mako 的模板读进来, 解析成语法树, 然后编译成 Python 程序 (和 Mako 一样是编译型模板)
  * 下载地址: http://code.google.com/p/eurasia/source/browse/trunk/Eurasia/template.py
  * 精巧地址: http://bit.ly/1rjgdz
 * 081020(16:24:22) 沈崴-wileishn:
支持 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%)

    
##endInc
## 练习::
## 可能的话
## 设计实用练习,保证每个练习都可以扩展出去
Line 41: Line 292:
== 为啥介多框架?! ==

还有人站着说话不腰痛的分析"[http://xlp223.yculblog.com/post.1634226.html 为何有如此多的python web 框架?]"
{{{脚注:
访问地址:http://xlp223.yculblog.com/post.1634226.html
精巧地址:http://tinyurl.com/6yajuo
}}}
 * 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
精巧地址:http://tinyurl.com/6kv9j3
}}}

{{{注意:
在上述文章中,作者为了展示任何人可以通过Python快速创建自个儿的Web应用框架,
当场使用 9个文件创建并运行了一个含有足够功能的框架!
详细请参看本章最后的小结部分
}}}

=== Joe Gregorio的超级框架 ===
 组成::
  1. model.py{{{#!python
from sqlalchemy import Table, Column, String
import dbconfig

entry_table = Table('entry', dbconfig.metadata,
             Column('id', String(100), primary_key=True),
             Column('title', String(100)),
             Column('content', String(30000)),
             Column('updated', String(20), index=True)
         )
}}}
  1. dbconfig.py{{{#!python
from sqlalchemy import *

metadata = BoundMetaData('sqlite:///tutorial.db')
}}}
  1. manage.py{{{#!python
import os, sys

def create():
    from sqlalchemy import Table
    import model
    for (name, table) in vars(model).iteritems():
        if isinstance(table, Table):
            table.create()

def run():
    import urls
    if os.environ.get("REQUEST_METHOD", ""):
        from wsgiref.handlers import BaseCGIHandler
        BaseCGIHandler(sys.stdin, sys.stdout, sys.stderr, os.environ).run(urls.urls)
    else:
        from wsgiref.simple_server import WSGIServer, WSGIRequestHandler
        httpd = WSGIServer(('', 8080), WSGIRequestHandler)
        httpd.set_app(urls.urls)
        print "Serving HTTP on %s port %s ..." % httpd.socket.getsockname()
        httpd.serve_forever()

if __name__ == "__main__":
   if 'create' in sys.argv:
        create()
   if 'run' in sys.argv:
        run()

}}}
  1. view.py{{{#!python
import selector
import view

urls = selector.Selector()
urls.add('/blog/', GET=view.list)
urls.add('/blog/{id}/', GET=view.member_get)
urls.add('/blog/;create_form', POST=view.create, GET=view.list)
urls.add('/blog/{id}/;edit_form', GET=view.member_get, POST=view.member_update)
}}}
  1. model.py{{{#!python
import robaccia
import model

def list(environ, start_response):
    rows = model.entry_table.select().execute()
    return robaccia.render(start_response, 'list.html', locals())

def member_get(environ, start_response):
    id = environ['selector.vars']['id']
    row = model.entry_table.select(model.entry_table.c.id==id).execute().fetchone()
    return robaccia.render(start_response, 'entry.html', locals())

def create(environ, start_response):
    pass
def create_form(environ, start_response):
    pass
def member_edit_form(environ, start_response):
    pass
def member_update(environ, start_response):
    pass
}}}
  1. robaccia.py{{{#!python
import kid
import os

extensions = {
    'html': 'text/html',
    'atom': 'application/atom+xml'
    }

def render(start_response, template_file, vars):
    ext = template_file.rsplit(".")
    contenttype = "text/html"
    if len(ext) > 1 and (ext[1] in extensions):
        contenttype = extensions[ext[1]]

    template = kid.Template(file=os.path.join('templates', template_file), **vars)
    body = template.serialize(encoding='utf-8')

    start_response("200 OK", [('Content-Type', contenttype)])
    return [body]
}}}
  1. 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
}}}
  1. 初始化数据{{{
~$ 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")
}}}
  1. 独立运行{{{
~$ python manage.py run
Serving HTTP on 0.0.0.0 port 8080 ...

}}}
  1. 通过 cgi 在各种Web服务器中运行{{{
#!/usr/bin/python2.4
import manage
manage.run()
}}}

 能力::
  * 通过 SQLAlchemy 进行对象化高效数据库操作的
   * SQLAlchemy官方网站 http://www.sqlalchemy.org/
  * 使用 WSGI(Web 服务器网关接口)模式运行的
   * WSGI官方网站: http://www.wsgi.org/wsgi/What_is_WSGI
   * 精巧地址: http://bit.ly/3IkgU4
  * 可对URL进行映射管理的
  * 使用 Kid 模板系统,高效输出数据的
   * Kid官方网站 http://www.kid-templating.org/
   * 精巧地址: http://bit.ly/2YDxPd
  * 全功能Web应用框架!

== 使用 ==
   * 以实用的小例子,快速介绍知识点涉及技术的应用方式方法
   * 根据实例进行语法的快速讲解;注意给出资料指引
   * 经典代码举例

== 问题 ==
   * 指出知识点应用中常常遇见的问题,和解决思路
   * 根据实用体验,说明如何理解以及实际使用时的理性思考方向
   *

== 探讨 ==
   进一步介绍相关的或是深入的知识领域...
   * 组织实用的技巧类代码

 
Eurasia3 前面已经
 * 用 895 行单文件实现了 ZODB
  * 下载地址: http://code.google.com/p/eurasia/source/browse/trunk/Eurasia/shelve2.py
  * 精巧地址: http://bit.ly/1yzuqZ
 * 这次更过分了, Mako 只有 377 行。把类似于 Mako 的模板读进来, 解析成语法树, 然后编译成 Python 程序 (和 Mako 一样是编译型模板)
  * 下载地址: http://code.google.com/p/eurasia/source/browse/trunk/Eurasia/template.py
  * 精巧地址: http://bit.ly/1rjgdz
 * 081020(16:24:22) 沈崴-wileishn:
支持 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 项目主站上

== 小结 ==
  总体回顾,给出相关阅读和思考指引

## 练习::
## 可能的话
## 设计实用练习,保证每个练习都可以扩展出去

    
##endInc

status

校对

ZoomQuiet

完成度:25%

TableOfContents

PCS304 Web应用框架纵览

为啥介多框架?!

还有人站着说话不腰痛的分析"[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应用框架, 当场使用 9个文件创建并运行了一个含有足够功能的框架! 详细请参看本章最后的小结部分 }}}

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()
    
  • main.cgi ~ 服务器运行脚本

    import manage
    manage.run()
    1. 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)
      
    2. 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
      
    3. 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]
      
    4. 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 ...
    4. 通过 cgi 在各种Web服务器中运行

      import manage
      manage.run()
    能力
  • 现状

    由来

    探讨

    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 (请 阿北或是朞其它豆瓣成员 撰写)
          |  +-- Quixote (请 阿北 撰写)
          |  +-- Django (HY自写)
          |  \-- UliWeb (请Limodou撰写)
          +-- 选择
          |  +-- 个人
          |  +-- 团队
          |  \-- 企业
          \-- 小结
            \-- 选择的痛苦


    反馈

    创建 by -- ::-- ["kongove"] [DateTime(2008-11-08T10:16:37Z)]

    PageComment2

    [:/PageCommentData:PageCommentData]

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