Size: 3162
Comment:
|
Size: 9854
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
##language:zh ##OBP项目图书reST通用文章模板 ||status|| 草稿 ||HuangYi; 30%|| [[TableOfContents]] 那么小白决定进一步探索 python web开发更高级一点的技术了,行者建议他从基础入手。 当用户在浏览器中输入网址,浏览器便找到web服务器,向它发起http请求, web服务器再找到web应用程序执行之,并把结果返回给客户端浏览器。 那么做web开发之前首先要有web服务器才行,开发阶段最好使用一个简单方便的开发服务器。 等开发调试完毕,再将代码部署到 apache、lighttpd 等成熟高效的web服务器, 放心,使用python做web开发,最后部署的阶段是很轻松的,在本章的后面便会提到。 |
|
Line 3: | Line 19: |
{{{#!python | 那么 python2.5 就自带了一个叫做 wsgiref 模块,它提供一些专业 web 开发所需要的一些基础工具,比如一个开发服务器: {{{#!python # -*- coding: utf-8 -*- |
Line 5: | Line 24: |
# 定义一个输出 hello world 和环境变量的简单web应用程序 |
|
Line 6: | Line 27: |
start_response('200 OK', {}) yield 'Hello world' |
# 输出 http 头 start_response('200 OK', [('Content-type','text/plain')]) # 准备输出的内容 content = [] content.append('Hello world') |
Line 9: | Line 33: |
yield '%s : %s' % (key, value) |
content.append('%s : %s' % (key, value)) # 输出,根据 wsgi 协议,返回的需要是一个迭代器,返回一个 list 就可以 return ['\n'.join(content)] # 构造开发服务器对象,设置绑定的地址和端口,并把 hello world 应用程序传给他 |
Line 12: | Line 39: |
# 启动开发服务器 | |
Line 15: | Line 43: |
把以上代码以utf-8编码保存成python程序,不妨命名为 main.py。然后执行上面这个程序后,打开浏览器,访问 http://localhost:8000 即可看到输出的内容。 {{{注意:: wsgiref 带的这个开发服务器调用应用程序所使用的协议叫做 wsgi,wsgiref就是对wsgi协议的 一个参考实现,wsgi 协议内容可以参考:URL ,在这里你只需要知道,hello_app 的第一个参数environ 是包含web环境变量的字典,类似于 cgi 的环境变量,里面包含了请求的URL,请求客户端的IP等信息。 第二个参数 start_response 是一个函数,调用它来输出 http 状态码和响应头。 }}} |
|
Line 17: | Line 54: |
{{{#!python from mako import Template tmpl = Template('./simple.html') print tmpl.render(data = {'a':1, 'b':2}) }}} simple.html |
但是 web程序大部分时候都是要返回一个 html 页面的,而把一个复杂的 html 页面 代码放到python代码里面就太丑陋了,应该把它放到一个模板里去,把页面展现与 业务逻辑分离开来。 python里面的模板引擎主要有mako、genshi、jinja等。mako 主要特点在于模板里面 可以比较方便的嵌入python代码,而且执行效率一流;genshi 的特点在于基于 xml, 非常简单易懂的模板语法,对于热爱xhtml的朋友来说是很好的选择,同时也可以嵌入python 代码,实现一些复杂的展现逻辑;jinja 和 genshi 一样拥有很简单的模板语法,只是不 依赖于 xml 的格式,同样很适合设计人员直接进行模板的制作,同时也可以嵌入python 代码实现一些复杂的展现逻辑。 小白看 mako 挺顺眼的,于是就钻研了它一把。 可以到这里 http://www.makotemplates.org/download.html 找到最新版本的下载地址,下载解压, 然后执行 python setup.py install 就可以了。 下面的代码就是写的一个简单的 mako 模板文件,里面使用 python 的 for 循环来把 data 这个字典的 内容填充到一个html列表(mako模板的详细语法请参考:URL)。 |
Line 32: | Line 80: |
% for key, value in environ.items(): | % for key, value in data.items(): |
Line 42: | Line 90: |
和 wsgiref 整合: {{{#!python |
然后要做的就是给模板传递一个叫做 data 的字典对象了,可以编写如下三句代码实现: {{{#!python # -*- coding: utf-8 -*- # 导入模板对象 from mako import Template # 使用模板文件名构造模板对象 tmpl = Template('./simple.html') # 构造一个简单的字典填充模板,并print出来 print tmpl.render(data = {'a':1, 'b':2}) }}} 执行以上程序,就可以看到通过模板输出的 html 代码了。 现在再看看如何把它用到web应用中来吧。 {{{#!python # -*- coding: utf-8 -*- |
Line 47: | Line 109: |
Line 50: | Line 113: |
start_response('200 OK', {}) return content |
start_response('200 OK', [('Content-type','text/html')]) return [content] |
Line 57: | Line 120: |
执行这个程序,并访问 http://localhost:8000 你就可以看到通过模板输出的页面了。 |
|
Line 59: | Line 124: |
model.py {{{#!python |
作为一个动态网站,有很多数据需要持久存储,关系数据库在这方面通常都是不二选择。 当小白向行者问道如何才能简化对数据库的访问时,行者郑重向小白推荐了 sqlalchemy 这个库。 sqlalchemy 是一个 ORM (对象-关系映射)库,提供python对象与关系数据库之间的映射, 可以通过 python 对象很方便地对关系数据库进行操纵,比如使用python代码描述数据库结构, 创建数据库,执行插入、查询、删除等数据库操作,非常方便。除了这些 ORM 的基本功能外, sqlalchemy 还支持Model的继承,自引用(Self-referential)、eager loading、lazy loading 等等, 还可以直接将 Model 映射到自定义的 SQL 语句。可以说既有不输于 Hibernate 的强大功能, 同时不失 Python 的优雅简洁。 在这里 http://www.sqlalchemy.org/download.html 找到最新版本的下载地址,下载解压, 然后执行 python setup.py install 进行安装。 代码胜千言,sqlalchemy 到底可以做什么,直接上代码展示下 sqlalchemy 的基本功能吧: {{{#!python # -*- coding: utf-8 -*- from sqlalchemy.ext.declarative import declarative_base # 创建数据库引擎,这里我们直接使用 python2.5 自带的数据库引擎:sqlite, # 直接在当前目录下建立名为 data.db 的数据库 engine = create_engine('sqlite:///data.db') # sqlalchemy 中所有数据库操作都要由某个session来进行管理 # 关于 session 的详细信息请参考:http://www.sqlalchemy.org/docs/05/session.html Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() class Dictionay(Base): # python 对象对应关系数据库的表名 __tablename__ = 't_dictionay' # 两个字段: key = Column('key', String(255), primary_key=True) value = Column('value', String(255)) # 创建数据库 Base.metadata.create_all(engine) session = Session() for item in ['python','ruby','java']: dictionay = Dictionay(key=item, value=item.upper()) session.add(dictionay) # 提交session,在这里才真正执行数据库的操作,添加三条记录到数据库 session.commit() # 查询Dictionary类对应的数据 for dictionay in session.query(Dictionary): print dictionay.name, dictionay.value }}} 直接执行这个程序就可以了。 不过这是个单独的 demo,要把放到 web 应用里面,还需要先对它的结构重新组织一下。 先剥离出一个公用的 model.py 文件。 {{{#!python # -*- coding: utf-8 -*- |
Line 71: | Line 191: |
# 创建数据库 Base.metadata.create_all(engine) session = Session() for item in ['python','ruby','java']: dictionay = Dictionay(key=item, value=item.upper()) session.add(dictionay) session.commit() for dictionay in session.query(Dictionary): print dictionay.name, dictionay.value }}} 上面是个 demo,下面我们把它放到web应用中去。 model.py {{{#!python from sqlalchemy.ext.declarative import declarative_base engine = create_engine('sqlite:///data.db') Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() class Dictionay(Base): __tablename__ = 't_dictionay' key = Column('key', String(255), primary_key=True) value = Column('value', String(255)) }}} create_db.py {{{#!python |
}}} 然后建立一个创建数据库并插入一些测试数据的单独的程序,创建数据库只需要一开始做一次就可以了。 {{{#!python # -*- coding: utf-8 -*- # 导入公用的 model 模块 |
Line 118: | Line 212: |
和 wsgiref 整合 {{{#!python |
最后再将这个功能加入到我们的 web 程序里面来: {{{#!python # -*- coding: utf-8 -*- |
Line 122: | Line 218: |
# 导入公用的 model 模块 | |
Line 125: | Line 222: |
# 查询到所有 Dictionary 对象 | |
Line 126: | Line 224: |
# 然后根据 Dictionary 对象的 name、value 属性把列表转换成一个字典 | |
Line 128: | Line 227: |
# 填充模板 | |
Line 131: | Line 231: |
start_response('200 OK', {}) return content |
start_response('200 OK', [('Content-type','text/plain')]) return [content] |
Line 137: | Line 237: |
执行上面这个文件并打开浏览器访问 http://localhost:8000/ 就可以看到刚才创建的三条测试数据了。 == yaro == TODO 引入一个request、response对象的实现 http://lukearno.com/projects/yaro/ == beaker == TODO 引入 session 的实现:beaker http://beaker.groovie.org/ TODO 其他组件的介绍 现在让我们回头看一下,我们最终得到了一个什么样的程序。 TODO 成熟 web 框架介绍 |
status |
草稿 |
HuangYi; 30% |
那么小白决定进一步探索 python web开发更高级一点的技术了,行者建议他从基础入手。
当用户在浏览器中输入网址,浏览器便找到web服务器,向它发起http请求, web服务器再找到web应用程序执行之,并把结果返回给客户端浏览器。
那么做web开发之前首先要有web服务器才行,开发阶段最好使用一个简单方便的开发服务器。 等开发调试完毕,再将代码部署到 apache、lighttpd 等成熟高效的web服务器, 放心,使用python做web开发,最后部署的阶段是很轻松的,在本章的后面便会提到。
wsgiref
那么 python2.5 就自带了一个叫做 wsgiref 模块,它提供一些专业 web 开发所需要的一些基础工具,比如一个开发服务器:
1 # -*- coding: utf-8 -*-
2 import wsgiref
3
4 # 定义一个输出 hello world 和环境变量的简单web应用程序
5 def hello_app(environ, start_response):
6 # 输出 http 头
7 start_response('200 OK', [('Content-type','text/plain')])
8 # 准备输出的内容
9 content = []
10 content.append('Hello world')
11 for key, value in environ.items():
12 content.append('%s : %s' % (key, value))
13 # 输出,根据 wsgi 协议,返回的需要是一个迭代器,返回一个 list 就可以
14 return ['\n'.join(content)]
15
16 # 构造开发服务器对象,设置绑定的地址和端口,并把 hello world 应用程序传给他
17 server = wsgiref.make_server('localhost', 8000, hello_app)
18 # 启动开发服务器
19 server.serve_forever()
把以上代码以utf-8编码保存成python程序,不妨命名为 main.py。然后执行上面这个程序后,打开浏览器,访问 http://localhost:8000 即可看到输出的内容。
{{{注意::
- wsgiref 带的这个开发服务器调用应用程序所使用的协议叫做 wsgi,wsgiref就是对wsgi协议的 一个参考实现,wsgi 协议内容可以参考:URL ,在这里你只需要知道,hello_app 的第一个参数environ 是包含web环境变量的字典,类似于 cgi 的环境变量,里面包含了请求的URL,请求客户端的IP等信息。 第二个参数 start_response 是一个函数,调用它来输出 http 状态码和响应头。
}}}
mako
但是 web程序大部分时候都是要返回一个 html 页面的,而把一个复杂的 html 页面 代码放到python代码里面就太丑陋了,应该把它放到一个模板里去,把页面展现与 业务逻辑分离开来。
python里面的模板引擎主要有mako、genshi、jinja等。mako 主要特点在于模板里面 可以比较方便的嵌入python代码,而且执行效率一流;genshi 的特点在于基于 xml, 非常简单易懂的模板语法,对于热爱xhtml的朋友来说是很好的选择,同时也可以嵌入python 代码,实现一些复杂的展现逻辑;jinja 和 genshi 一样拥有很简单的模板语法,只是不 依赖于 xml 的格式,同样很适合设计人员直接进行模板的制作,同时也可以嵌入python 代码实现一些复杂的展现逻辑。
小白看 mako 挺顺眼的,于是就钻研了它一把。 可以到这里 http://www.makotemplates.org/download.html 找到最新版本的下载地址,下载解压, 然后执行 python setup.py install 就可以了。
下面的代码就是写的一个简单的 mako 模板文件,里面使用 python 的 for 循环来把 data 这个字典的 内容填充到一个html列表(mako模板的详细语法请参考:URL)。
<html> <head> <title>简单mako模板</title> </head> <body> <h5>Hello World!</h5> <ul> % for key, value in data.items(): <li> ${key} - ${value} <li> % endfor </ul> </body> </html>
然后要做的就是给模板传递一个叫做 data 的字典对象了,可以编写如下三句代码实现:
执行以上程序,就可以看到通过模板输出的 html 代码了。 现在再看看如何把它用到web应用中来吧。
1 # -*- coding: utf-8 -*-
2 import wsgiref
3 from mako import Template
4
5 def hello_app(environ, start_response):
6 tmpl = Template('./simple.html')
7 content = tmpl.render(data=environ)
8 start_response('200 OK', [('Content-type','text/html')])
9 return [content]
10
11 server = wsgiref.make_server('localhost', 8000, hello_app)
12 server.serve_forever()
执行这个程序,并访问 http://localhost:8000 你就可以看到通过模板输出的页面了。
sqlalchemy
作为一个动态网站,有很多数据需要持久存储,关系数据库在这方面通常都是不二选择。 当小白向行者问道如何才能简化对数据库的访问时,行者郑重向小白推荐了 sqlalchemy 这个库。
sqlalchemy 是一个 ORM (对象-关系映射)库,提供python对象与关系数据库之间的映射, 可以通过 python 对象很方便地对关系数据库进行操纵,比如使用python代码描述数据库结构, 创建数据库,执行插入、查询、删除等数据库操作,非常方便。除了这些 ORM 的基本功能外, sqlalchemy 还支持Model的继承,自引用(Self-referential)、eager loading、lazy loading 等等, 还可以直接将 Model 映射到自定义的 SQL 语句。可以说既有不输于 Hibernate 的强大功能, 同时不失 Python 的优雅简洁。
在这里 http://www.sqlalchemy.org/download.html 找到最新版本的下载地址,下载解压, 然后执行 python setup.py install 进行安装。
代码胜千言,sqlalchemy 到底可以做什么,直接上代码展示下 sqlalchemy 的基本功能吧:
1 # -*- coding: utf-8 -*-
2 from sqlalchemy.ext.declarative import declarative_base
3
4 # 创建数据库引擎,这里我们直接使用 python2.5 自带的数据库引擎:sqlite,
5 # 直接在当前目录下建立名为 data.db 的数据库
6 engine = create_engine('sqlite:///data.db')
7 # sqlalchemy 中所有数据库操作都要由某个session来进行管理
8 # 关于 session 的详细信息请参考:http://www.sqlalchemy.org/docs/05/session.html
9 Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
10 Base = declarative_base()
11
12 class Dictionay(Base):
13 # python 对象对应关系数据库的表名
14 __tablename__ = 't_dictionay'
15 # 两个字段:
16 key = Column('key', String(255), primary_key=True)
17 value = Column('value', String(255))
18
19 # 创建数据库
20 Base.metadata.create_all(engine)
21
22 session = Session()
23 for item in ['python','ruby','java']:
24 dictionay = Dictionay(key=item, value=item.upper())
25 session.add(dictionay)
26
27 # 提交session,在这里才真正执行数据库的操作,添加三条记录到数据库
28 session.commit()
29
30 # 查询Dictionary类对应的数据
31 for dictionay in session.query(Dictionary):
32 print dictionay.name, dictionay.value
直接执行这个程序就可以了。 不过这是个单独的 demo,要把放到 web 应用里面,还需要先对它的结构重新组织一下。
先剥离出一个公用的 model.py 文件。
1 # -*- coding: utf-8 -*-
2 from sqlalchemy.ext.declarative import declarative_base
3
4 engine = create_engine('sqlite:///data.db')
5 Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
6 Base = declarative_base()
7
8 class Dictionay(Base):
9 __tablename__ = 't_dictionay'
10 key = Column('key', String(255), primary_key=True)
11 value = Column('value', String(255))
然后建立一个创建数据库并插入一些测试数据的单独的程序,创建数据库只需要一开始做一次就可以了。
1 # -*- coding: utf-8 -*-
2 # 导入公用的 model 模块
3 from model import Base, Session, Dictionary
4
5 # 创建数据库
6 Base.metadata.create_all(engine)
7
8 # 插入初始数据
9 session = Session()
10 for item in ['python','ruby','java']:
11 dictionay = Dictionay(key=item, value=item.upper())
12 session.add(dictionay)
13
14 session.commit()
最后再将这个功能加入到我们的 web 程序里面来:
1 # -*- coding: utf-8 -*-
2 import wsgiref
3 from mako import Template
4 # 导入公用的 model 模块
5 from model import Session, Dictionary
6 def hello_app(environ, start_response):
7 session = Session()
8 # 查询到所有 Dictionary 对象
9 dictionaries = session.Query(Dictionary)
10 # 然后根据 Dictionary 对象的 name、value 属性把列表转换成一个字典
11 data = dict([(dictionary.name, dictionary.value) for dictionary in dictionaries])
12
13 # 填充模板
14 tmpl = Template('./simple.html')
15 content = tmpl.render(data=data)
16
17 start_response('200 OK', [('Content-type','text/plain')])
18 return [content]
19
20 server = wsgiref.make_server('localhost', 8000, hello_app)
21 server.serve_forever()
执行上面这个文件并打开浏览器访问 http://localhost:8000/ 就可以看到刚才创建的三条测试数据了。
yaro
TODO 引入一个request、response对象的实现 http://lukearno.com/projects/yaro/
beaker
TODO 引入 session 的实现:beaker http://beaker.groovie.org/
TODO 其他组件的介绍
现在让我们回头看一下,我们最终得到了一个什么样的程序。
TODO 成熟 web 框架介绍