web.py 的首页提供了一个 13 行的例子来演示如何开始一个应用,但其网站上似乎就没有别的更进一步的例子了。这两天简短学习了一下,写一个进阶例程。包括:读取 GET/POST 变量,以及模板的使用。
#!/usr/bin/python
import web
urls = (
'/sample', 'sample',
'/(.*)', 'hello'
)
class hello:
def GET(self, name):
i = web.input(times=1)
if not name: name = 'world'
for c in xrange(int(i.times)): print 'Hello,', name+'!'
class sample:
def _request(self):
render = web.template.render('templates/')
cache = False
i = web.input(fname = 'yingbo', sname = 'qiu')
#交换 fname, sname 的值
firstName = i.sname
surName = i.fname
print render.sample(firstName, surName)
def GET(self):
self._request()
def POST(self):
self._request()
if __name__ == "__main__":
import os
os.environ['PHP_FCGI_CHILDREN'] = "1" #FastCGI 运行模式
web.run(urls, globals())
模板:templates/sample.html
$def with (firstName, surName)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>dup2.net</title>
</head>
<body>
<form action="sample" method="post">
名:<input type="text" name="fname" value="$firstName" />
姓:<input type="text" name="sname" value="$surName" />
<input type="submit" value="提交" />
</form>
</body>
</html>
访问 http://www.dup2.net/papp/sample 就可以看到效果。这个 sample 可以接受 GET/POST 请求。参数为 fname 和 sname。执行结果就是将这两个值交换显示。
web.py 每个 URL 请求分发到一个类。这里就把 sample 分发给 sample 类,其它的所有 URL 分发给 hello 类。访问一下 http://www.dup2.net/papp/ladf/badf?times=3 看看 hello 的效果。
HTTP GET 和 POST 分别执行 class 里面的 method。使用 web.input() 来取得 request 参数和值。
然后用 web.template.render() 初始化模板目录。方法名 "sample" 对应的 "sample.html" 模板文件
申明一点,这里的例子都是基于 web.py 0.2 版本的。现在网上的 web.py 中文教程是基于 0.1 的,如果你看到的文章一开始说要安装什么 Cheetah,那肯定不适用现在的情况了。
首先说的是 Python 连 MySQL,以及 UTF-8 字符集的事情。我这里假设你的应用是纯 UTF-8 的,而且使用 MySQL 4.1 以上的版本。
Python for MySQL 的连接扩展在 mysql-python,Debian Sarge 的包里面是 1.2.1c2 版,是不支持 4.1 的 Charset 特性的,最新的 1.2.1_p2 版支持的很好,只不过从这个版本开始必须依赖 Python2.4 了。
当使用 mysql-python connect()的时候有两个重要参数,charset,use_unicode。charset 就是指定连接以后 set names 的字符集;use_unicode 则指定 fetch result 的结果是用 'unicode string' or 'string' 类型 ? 由于最后输出的模板都是按照 string 来解析的,为了能正确运算,必须把这里设置成 0
web.py 类似 Java Servelet,可以在程序出错的时候抛出一大块异常;而且因为直接处理所有的 URL,所以它也内置一个自定义 url not found 的机制。
例子:首先是初始化部分的代码
def mynotfound():
render = web.template.render('templates/')
print render._404()
web.webapi.internalerror = web.debugerror
web.webapi.notfound = mynotfound
if __name__ == "__main__":
import os
os.environ['PHP_FCGI_CHILDREN'] = "1" #FastCGI 运行模式
web.config.db_parameters = dict(dbn='mysql', user='webpy', pw='passwordofwebpy', /
host='localhost',port=3306,db='club',charset='utf8',/
use_unicode=0)
web.run(urls, globals())
上面定义了新的 404 处理函数以及用 web.debugerror 代替原来的 500 处理函数,debugerror 可以抛出一个非常漂亮的异常页面。在 __main__ 函数里面设定了 mysql 的连接参数,这里连接到一个叫 club 的数据库
增加一个对所有以 'sample/' 开头的 URL 分发类 samples
urls = (
'/sample', 'sample',
'/sample/(.*)', 'samples',
'/(.*)', 'hello'
)
class samples:
GET = web.autodelegate('GET_')
POST = web.autodelegate('POST_')
def show_signup(self, users):
render = web.template.render('templates/sample/')
print render.signup(users)
def GET_signup(self):
users = web.select('user')
self.show_signup(users)
def POST_signup(self):
i = web.input()
web.insert('user',
user_name=i.user_name,
user_email=i.user_email,
user_passport=i.user_passport)
users = web.select('user')
self.show_signup(users)
注意:这里用了 autodelegate ,来把 sample/abc 的 GET 方法转到 GET_abc 方法去处理
运行实例:
访问 http://www.dup2.net/papp/sample/notfound 可以看到我自定义的 _404 输出结果
访问 http://www.dup2.net/papp/sample/signup可以执行我这里访问 MySQL 的例子.
我这里的 email 是设置成 unique key 的,这样可以在这个页面提交表单内容里面把 email 赋值为已经存在的 email,比如 spam@notinput-realemail-here.org,哈,就可以看到一个很帅的异常了..