web.py 0.3 教程
| web.py 0.3 教程 web.py 是一个漂亮的 Python web 框架, 当前最新版本是 0.3,增加了 sessions、subdir_application 和 subdomain_application 以及更好的数据库支持。 目录:安装第一个程序URL 处理 正则映射 自动映射开发静态文件重定向多个应用程序 基于子目录的应用程序 基于子域名的应用程序测试 doctest unittest会话 session cookies 设置 读取发邮件 用 gmail 发邮件获取客户端信息 web.ctx 例子 ctx 里的数据 Request Response模板 变量替换 连接多行 异常 注释 代码 传递变量用户输入 表单 重复表单项 文件上传 例子 注意数据库 <!–note–>安装 可以从 github.com/webpy/webpy 里获得最新的 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 此外,也许您还需要安装 python-cheetah, python-flup 第一个程序 第一个程序就以 你好,世界 来开始吧 以下是代码片段: #!/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 端口了,在浏览器中访问http://0.0.0.0: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 weburls = ( “/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 ” + pathapp_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 ” + pathapp = 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 比如 www.example.com (和 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) 测试 doctest 以下是代码片段: import weburls = ( “/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!” unittest 以下是代码片段: import 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() 会话 session web.py 0.3 正式提供了基于 cookie 的 session 支持。 以下是代码片段: import weburls = ( “/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, andreturned 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 browser 2. 有预设值,避免异常 以下是代码片段: 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’, ‘http://google.com’) 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 http://example.org homedomain — ??? http://example.org 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: <h1>你好,$name!</h1> $else: <h1>你好,世界!</h1> 注意模板文件首行要个 $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) PEP 215. 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])<b>$mapping['a'][0]</b> 传递变量 可以这样设置模板里的全局变量 以下是代码片段: 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)…<title>$s.title</title>…<ul> $for entry in s.entrys: <li>$entry</li></ul> 用户输入 表单 重复表单项 复选框有重复的表单项,譬如 http://example.com?id=10&id=20 这样的请求,可以用类似下边代码获得多个 id 项值 以下是代码片段: class SomePage: def GET(self): user_data = web.input(id=[]) return “<h1>” + “,”.join(user_data.id) + “</h1>” 文件上传 例子 以下是代码片段: import web urls = (’/upload’, ‘Upload’) class Upload: def GET(self): return “”"<html><head></head><body><form method=”POST” enctype=”multipart/form-data” action=”"><input type=”file” name=”myfile” /><br/><input type=”submit” /></form></body></html>”"” 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’) |
0 条评论 发表评论