是一个漂亮的 Python web 框架,
当前最新版本是 0.3,增加了 sessions、subdir_application 和 subdomain_application 以及更好的数据库支持。
目录:
安装
可以从 里获得最新的 web.py
执行下列命令抓取
git clone git://github.com/webpy/webpy.git
git clone git://github.com/webpy/webpy.git
之后可以直接将抓回来的 webpy/web/ 文件夹拷到 web.py 程序目录里使用,
或者执行下列命令将 web.py 安装到系统里
cd webpy
python setup.py build
sudo python setup.py install
此外,也许您还需要安装 ,
第一个程序第一个程序就以 你好,世界 来开始吧
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import web
# URL 规则
urls = (
'/(.*)', 'hello'
)
# 应用程序
app = web.application(urls, globals())
class hello:
def GET(self, name):
if not name: name = 'world'
web.header('Content-Type', 'text/html; charset=UTF-8')
return '你好,' + 世界 + '!'
# 启动
if __name__ == "__main__":
app.run()
将他保存为 code.py,在命令行执行
python code.py
现在这个 web.py 应用程序就运行了一个 web 服务器默认监听 8080 端口了,在浏览器中访问 ,应该就可以看到 “您好,世界!” 了。
在命令行的 code.py 后加参数 "IP 地址:端口" 来控制 web 服务器的监听范围
比如监听 8000 端口
python code.py 0.0.0.0:8000
或者,只接受 192.168.1.25 来的 8086 端口
python code.py 0.0.0.0:8000
URL 处理web.py 0.3 有两种方式处理 URL,
有 urls 指定,或由元类自动映射
正则映射web.application() 用 urls 将路径的正则匹配映射到元类
import web
urls = (
"/hello", "hello",
"/magic/.*", "magic"
)
app = web.application(urls, globals())自动映射web.auto_application() 类似于 web.application() ,但自动根据元类来构造 urls
import web
app = web.auto_application()
class hello(app.page):
def GET(self):
return "hello, world!"
开发
静态文件重定向
多个应用程序web.py 支持集成多个应用程序,或说将应用划分到多个子应用程序。
比如将 /blog 分出在 blog.py 里边
在 blog.py:
import web
urls = (
"", "reblog",
"/(.*)", "blog",
)
class reblog:
def GET(self): raise web.seeother('/')
class blog:
def GET(self, path):
return "blog " + path
app_blog = web.application(urls, locals())在 code.py:
import web
import blog
urls = (
"/blog", blog.app_blog,
"/(.*)", "index",
)
class index:
def GET(self, path):
return "hello " + path
app = web.application(urls, locals())
基于子目录的应用程序可以根据子目录来划分应用程序,
比如将 wiki.py , blog.py , auth.py 分出来
import web
import wiki
import blog
import auth
mapping = (
"/wiki", wiki.app,
"/blog", blog.app,
"/auth", auth.app,
)
app = web.subdir_application(mapping)
基于子域名的应用程序也可以根据子域名来划分应用程序,这可以方便做 virtual hosting
比如
(和 example.com)是 mainsite
XXXX.example.com 是 usersite
import web
import mainsite
import usersite
mapping = (
"(www\.)?example.com", mainsite.app,
".*\.example.com", usersite.app,
)
app = web.subdomain_application(mapping)
测试doctestimport web
urls = (
"/hello", "hello",
)
app = web.application(urls, globals())
class hello:
"""Hello world example.
>>> response = app.request("/hello")
>>> response.data
'hello, world!'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
'text/plain'
"""
def GET(self):
web.header('Content-Type', 'text/plain')
return "hello, world!"
unittestimport unittest
from helloworld import app
class HelloWorldTest(unittest.TestCase):
def testHelloWorld(self):
response = app.request('GET', '/')
self.assertEquals(response.data, 'hello, world!')
self.assertEquals(response.headers['Content-Type'],
'text/plain')
self.assertEquals(response.status, '200 OK')
if __name__ == "__main__":
unittest.main()
会话sessionweb.py 0.3 正式提供了基于 cookie 的 session 支持。
import web
urls = (
"/count", "count",
"/reset", "reset"
)
app = web.application(urls, locals())
session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'count': 0})
class count:
def GET(self):
session.count += 1
return str(session.count)
class reset:
def GET(self):
session.kill()
return ""
if __name__ == "__main__":
app.run()上边 Session 的 initializer 参数可以是 dict 或 func,用来初始化 session。
web.py 的 session 存储有基于文件的 DiskStore 和基于数据库的 DBStore ,上边例子是 DiskStore。
也可以使用基于数据库的 DBStore。
使用 DBStore session 前需要在数据库建表
create table sessions (
session_id char(128) UNIQUE NOT NULL,
atime datetime NOT NULL default current_timestamp,
data text
);然后就可以
db = web.database(dbn='postgres', db='mydatabase', user='myname', pw='')
store = web.session.DBStore(db, 'sessions')
session = web.session.Session(app, store, initializer={'count': 0})
cookies设置可以用 web.setcookie() 、web.cookies() 来设置和读取 cookies
参数:
web.setcookie(name, value, expires="", domain=None, secure=False)- name (string) - The actual name of the cookie, as stored by the browser, and returned to the server.
- value (string) - The value you want stored under that name.
- expires (int) - Optionally, is the time in seconds until the browser should expire the cookie. Note: this must be an integer, not a string.
- domain (string) - The domain the cookie is valid for. By default, set to the host accessed, this allows you to set the domain, rather than just a host (such as .webpy.org).
- secure (bool)- If True, require that the cookie only be sent over HTTP/S.
例子
class CookieSet:
def GET(self):
i = web.input(age='25')
web.setcookie('age', i.age, 3600)
return "Age set in your cookie"读取有两个方法读取 cookie
1. 当 cookie 不存在时抛出异常
web.cookies().get(cookieName)
#cookieName is the name of the cookie submitted by the browser2. 有预设值,避免异常
foo = web.cookies(cookieName=defaultValue)
foo.cookieName # return the value (which could be default)
#cookieName is the name of the cookie submitted by the browser例子:
通过 web.cookies() 来访问
如果先前 web.setcookie() 设置了 age , 那可以这样读取
class CookieGet:
def GET(self):
c = web.cookies(age="25")
return "Your age is: " + c.age上边的当没有 cookie 时会异常,如果要考虑没有 cookie 的情况,可以类似下边这样:
class CookieGet:
def GET(self):
try:
return "Your age is: " + web.cookies().get('age')
except:
# Do whatever handling you need to, etc. here.
return "Cookie does not exist."发邮件用 gmail 发邮件先用 web.config 配置 smtp
web.config.smtp_server = 'smtp.gmail.com'
web.config.smtp_port = 587
web.config.smtp_username = 'cookbook@gmail.com'
web.config.smtp_password = 'secret'
web.config.smtp_starttls = True再用类似下边的发邮件
web.sendmail('cookbook@gmail.com', 'user@example.com', 'subject', 'message')或者可以附上邮件头web.sendmail('cookbook@webpy.org', ['user@example.com', 'user2@example.com'],
'subject', 'message',
cc='user1@example.com', bcc='user2@example.com',
headers=({'User-Agent': 'webpy.sendmail', 'X-Mailer': 'webpy.sendmail',})
)获取客户端信息web.ctx
例子class example:
def GET(self):
referer = web.ctx.env.get('HTTP_REFERER', '')
useragent = web.ctx.env.get('HTTP_USER_AGENT')
raise web.seeother(referer)
ctx 里的数据Request- environ a.k.a. env — a dictionary containing the standard WSGI environment variables
- home — the base path for the application
- homedomain — ???
- homepath — ???
- host — the domain requested by the user example.org
- ip — the IP address of the user xxx.xxx.xxx.xxx
- method — the HTTP method used GET
- path — the path requested by the user /articles/845
- protocol — the protocol used https
- query — an empty string if there are no query arguments otherwise a ? followed by the query string ?foo=amorphous&bar=blasphemous
- fullpath a.k.a. path + query — the full path requested including query arguments /articles/845?foo=amorphous&bar=blasphemous
Response- status — the HTTP status code (default '200 OK') 401 Unauthorized
- headers — a list of 2-tuples containing HTTP headers
- output — a string containing the response entity
模板web.py 支持模板(注意需要 python-cheetah)
先看看将 第一个程序 改为使用模板
写入 templates/hello.html :
$def with (name, todos={})
$if name:
你好,$name!
$else:
你好,世界!
注意模板文件首行要个 $def with() ,
在 code.py 里用
render = web.template.render('templates/')
class hello:
def GET(self, name):
return render.hello(name)
变量替换Look, a $string.
Hark, an ${arbitrary + expression}.
Gawk, a $dictionary[key].function('argument').
Cool, a $(limit)ing.
Stop, \$money isn't evaluated.We use basically the same semantics as (rejected) . Variables can go anywhere in a document.
连接多行If you put a backslash \
at the end of a line \
(like these) \
then there will be no newline.这会输出一整行
异常Here are some expressions:
$for var in iterator: I like $var!
$if times > max:
Stop! In the name of love.
$else:
Keep on, you can do it.
$try:
$get(input)
$except:
Couldn't find it.
That's all, folks.
注释$# Here's where we hoodwink the folks at home:
Please enter in your deets:
CC: [ ] $#this is the important one
SSN: $#Social Security Number#$ [ ]$# 到行末的是注释
代码可以将 python 语句放在行首的 "$ " 后(从"$ " 开始,之道行尾,或下一个 "$" )
$def with()
$ mapping = dict(a=[1, 2, 3],
$ b=[4, 5, 6])
$mapping['a'][0]传递变量可以这样设置模板里的全局变量
len = 'cn'
web.template.Template.globals[len] = len或者直接传递 globals()
web.template.Template.globals = globals()也可以在 metaclass.func 里传递 locals()
class index:
def GET(self):
title = '你好,世界'
entrys = ['第一个', '第二个', '第三个']
s = web.Storage(locals())
return render.index(s)而 templates/index.html 里用
$def with(s)
...$s.title
...
$for entry in s.entrys:
- $entry
用户输入表单重复表单项复选框有重复的表单项,譬如 id=10&id=20 这样的请求,可以用类似下边代码获得多个 id 项值
class SomePage:
def GET(self):
user_data = web.input(id=[])
return "" + ",".join(user_data.id) + ""
文件上传例子import web
urls = ('/upload', 'Upload')
class Upload:
def GET(self):
return """
"""
def POST(self):
x = web.input(myfile={})
return "filename: %s\n value: \n%s" % (x['myfile'].filename, x['myfile'].value)
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()注意- form 表单必须有属性 enctype="multipart/form-data",否则文件上传会不正常。
- 在 webpy 代码里,web.input() 参数必须有默认值(如上边的 myfile={} )。否则 web.input 不能获取文件名,而只能获取文件内容。
数据库
web.py 0.3 有更好的 db 处理
import web
db = web.database(dbn='postgres', db='todo', user='you', pw='')
db.select('todo')
db.select('todo', where='id=$id', vars={'id': 2})
db.query('SELECT * FROM todo')
转载:%B3%AC%C9%BD%C3%A8/blog/item/3d373be8f6b6ec39b80e2d83.html
阅读(1414) | 评论(0) | 转发(0) |