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, 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 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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值