前言
从Flask转到Tornado顺便玩一下简单的Web.py,随便写写。
安装
Pip(Python2.7):
pip install web.py
最新开发版本:
git clone git://github.com/webpy/webpy.git
Python3(实验版本,不完全的支持):
pip3 install web.py==0.40-dev1
最小的应用
#coding=utf-8
import web
urls = ('/', 'hello') #路由
class hello:
def GET(self):
return 'Hello,world!'
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
运行:python hello.py 8080
路由系统
路由
在上面的示例中,urls
为路由表,路由表为一个元组,定义了对应路由处理的类。
你可以用一个正则表达式来通配一个路由:
urls = ('/','hello','/(.*)','hello') #替换上面的路由表
def GET(self,name): #增加一个参数
return 'Hello,' + name
修改后试试访问 http://localhost:8080/me
跳转与重定向
raise web.seeother('/') #跳转到/目录
raise web.redirect('/')
这里两个跳转效果是一样的,但又有本质区别,web.seeother
给游览器的是303,让游览器通过GET跳转到新的页面,web.redirect
给游览器的是301,永久重定向,那这样的话对表单是极不有好的。
具体:https://www.cnblogs.com/wuguanglin/p/redirect.html
GET 与 POST
GET与POST是常用的数据交换方式,下面介绍在Web.py中如何处理这两种数据:
GET
在hello
的GET
函数中,添加一行,这会打印所有的GET参数:
print web.input()
#print web.input().get('test') 取指定参数
添加后访问 http://localhost:8080/?test=hello&test2=world
输出一个字典:<Storage {'test': u'hello', 'test2': u'world'}>
POST
POST需要我们在hello
中添加一个POST
函数,来处理POST请求:
def POST(self,name):
print web.data()
#print web.data().get('test') 取指定参数
return 'Hello,' + name
同GET方式输出一个字典(准确来说是是一个神奇的东西),这里也可以使用`web.input()`
获取环境信息
print web.ctx.ip #取客户端ip
你可以通过`web.ctx.`来取到其他的变量:
Request:
- environ 又被写做. env – 包含标准WSGI环境变量的字典
- home – 应用的http根路径(译注:可以理解为应用的起始网址,协议+站点域名+应用所在路径)例:http://example.org/admin
- homedomain – 应用所在站点(可以理解为协议+域名) http://example.org
- homepath – 当前应用所在的路径,例如: /admin
- host – 主机名(域名)+用户请求的端口(如果没有的话,就是默认的80端口),例如: example.org, example.org:8080
- ip – 用户的IP地址,例如: xxx.xxx.xxx.xxx
- method – 所用的HTTP方法,例如: GET
- path – 用户请求路径,它是基于当前应用的相对路径。在子应用中,匹配外部应用的那部分网址将被去掉。例如:主应用在code.py中,而子应用在admin.py中。在code.py中, 我们将/admin关联到admin.app。 在admin.py中, 将/stories关联到stories类。在 stories中, web.ctx.path就是/stories, 而非/admin/stories。形如: /articles/845
- protocol – 所用协议,例如: https
- query – 跟在’?’字符后面的查询字符串。如果不存在查询参数,它就是一个空字符串。例如: ?fourlegs=good&twolegs=bad
- fullpath 可以视为 path + query – 包含查询参数的请求路径,但不包括’homepath’。例如:/articles/845?fourlegs=good&twolegs=bad
Response:
- status – HTTP状态码(默认是’200 OK’) 401 Unauthorized 未经授权
- headers – 包含HTTP头信息(headers)的二元组列表。
- output – 包含响应实体的字符串。
参考:http://webpy.org/cookbook/ctx.zh-cn
自定义错误信息
在if __name__ == '__main__': app = web.application(urls,globals())
下添加两行:
app.notfound = notfound #404,定义由notfound函数处理
app.internalerror = internalerror #500,定义由internalerror函数处理
流
class Video: #生成器
def GET(self):
web.header('Content-type','video/mp4') #设置头
#web.header('Transfer-Encoding','chunked')
with open('test2.mp4','rb') as f:
data = f.read(2048) #每次读取2048字节
while data:
print len(data),'-',
yield data
data = f.read(2048)
Cookie
设置一个Cookie(在GET或POST方式内):
web.setcookie(name,value,time,domain,secure)
- name (string)名称
- value (string)值
- time (int,可选,如果为空仅本次会话有效)有效期,秒
- domain (string,可选)有效域
- secure (bool,可选)要求HTTPS
读取一个Cookie(在GET或POST方式内):
web.cookies().get(name) #空返回None
或
foo = web.cookies(cookieName=defaultValue) foo.cookieName #空返回默认值
模板
Web.py自带模板系统,但好像没有jinja2那样使起来顺手。
使用
1.一般使用
render = web.template.render('templates') #templates为模板文件夹
print render.hello(value1,value2,...) #hello为模板文件名,即`hello.html`
2.指定模板文件
render = web.template.frender(“templates/hello.html”)
return render(value1,value2,...)
3.或使用字符串
template = "$def with (name)\nHello $name"
hello = web.template.Template(template)
return hello('world')
语法
不写了:https://www.jianshu.com/p/7817641efe8d
解决中文问题
pip show web.py #查看包路径
修改web\template.py, line 1061:
return Template(open(path).read(), filename=path, **self._keywords)
为:
return Template(open(path,encoding='utf-8').read(), filename=path, **self._keywords)
表单
Web.py有一个表单模块:http://webpy.org/cookbook/forms.zh-cn
SSL支持
添加:
from web.wsgiserver import CherryPyWSGIServer
CherryPyWSGIServer.ssl_certificate = "path/to/ssl_certificate"
CherryPyWSGIServer.ssl_private_key = "path/to/ssl_private_key"