From:https://www.oschina.net/question/5189_4306
Web.py github 地址:https://github.com/webpy/webpy https://pypi.python.org/pypi/web.py
Web.py Cookbook 简体中文版:http://webpy.org/cookbook/index.zh-cn
web.py 0.3 新手指南:http://webpy.org/docs/0.3/tutorial.zh-cn
webpy 官网文档:http://webpy.org/
web.py 十分钟创建简易博客:http://blog.csdn.net/freeking101/article/details/53020728
一个简单的web.py论坛:http://www.cnblogs.com/russellluo/p/3240564.html
web.py 是一个Python 的web 框架,它简单而且功能强大。web.py 是公开的,无论用于什么用途都是没有限制的。而且相当的小巧,应当归属于轻量级的web 框架。但这并不影响web.py 的强大,而且使用起来很简单、很直接。在实际应用上,web.py 更多的是学术上的价值,因为你可以看到更多web 应用的底层,这在当今“抽象得很好”的web 框架上是学不到的 :) 如果想了解更多web.py,可以访问web.py 的官方文档。
先感受一下web.py 的简单而强大:
- import web
- urls = (
- '/(.*)', 'hello'
- )
- app = web.application(urls, globals())
- 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+'!'
- return 'Hello, ' + name + '!'
- if __name__ == "__main__":
- app.run()
上面就是一个基于web.py 的完整的Web 应用。将上面的代码保存为文件code.py,在命令行下执行python code.py。然后打开你的浏览器,打开地址:http://localhost:8080 或者 http://localhost:8080/test 没有意外的话(当然要先安装web.py,下面会有介绍),浏览器会显示“Hello, world”或者 “Hello, test”。
Linux 下运行
这是一个最简单的Hello world Web 应用。是不是很简单?!下面将较为详细地介绍下web.py 。
1. 安装
下载 web.py 的安装文件,将下载得到的文件 web.py 解压,进入解压后的文件夹,在命令行下执行:python setup.py install,在Linux 等系统下,需要root 的权限,可以执行:sudo python setup.py install。
2. URL 处理
对于一个站点来说,URL 的组织是最重要的一个部分,因为这是用户看得到的部分,而且直接影响到站点是如何工作的,例如:www.baidu.com ,其URLs 甚至是网页界面的一部分。而web.py 以简单的方式就能够构造出一个强大的URLs。
在每个web.py 应用,必须先import web 模块:
- import web
现在,我们须要告诉web.py URL 如何组织,让我们以一个简单例子开始:
- urls = (
- '/', 'index' )
在上面的例子中,第一部分是匹配URL的正则表达式,像/
、/help/faq
、/item/(\d+)
等(\d+
将匹配数字)。圆括号表示捕捉对应的数据以便后面使用。第二部分是接受请求的类名称,像index
、view
、welcomes.hello
(welcomes
模块的hello
类),或者get_\1
。\1
会被正则表达式捕捉到的内容替换,剩下来捕捉的的内容将被传递到你的函数中去。(‘index’)是一个类名,匹配的请求将会被发送过去。这行表示我们要URL/(首页)被一个叫index的类处理。
现在我们需要创建一个列举这些 url 的 application。
- app = web.application(urls, globals())
GET 和 POST : 区别
现在,我们需要编写index 类。当大部人浏览网页的时候,他们都没有注意到,浏览器是通过HTTP 跟World Wide Web 通信的。通信的细节不太重要,但要明白一点,用户是通过URLs(例如 / 或者 /foo?f=1)来请求web 服务器完成一定请求的(例如 GET 或者POST)。
GET 是最普遍的方法,用来请求一个页面。当我们在浏览器里输入“harvard.edu” 的时候,实际上它是向Web 服务器请求GET ”/“。另一个常见的方法是POST,常用于提交特定类型的表单,比如请求买什么东西。每当提交一个去做什么事情(像使用信用卡处理一笔交易)的请求时,你可以使用POST。这是关键,因为GET的URL可以明文传输提交的参数。如果提交的是一些重要的敏感信息,例如用户名,密码,则可能被别人抓包获取到。而 POST 则不会在 URL 上传输 提交的信息,POST 是通过表单提交信息。
在我们的web.py 代码中。我们清晰区分这两种方法:
- class index:
- def GET(self):
- print "Hello, world!"
当接收到一个GET 请求时,上面的GET 方法将会被web.py 调用。好的。现在,我们只需添加最后一行代码,让web.py 启动网页应用:
- if __name__ == "__main__":
- app.run()
上面告诉web.py 如何配置URLs,以及找寻的类在文件中的全局命名空间。然后为我们启动上面的应用。
整个 code.py 文件的内容如下:
- import web
- urls = (
- '/(.*)', 'hello'
- )
- app = web.application(urls, globals())
- 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+'!'
- return 'Hello, ' + name + '!'
- if __name__ == "__main__":
- app.run()
实际上web 应用的代码就只得上面的几行,而且这是一个完整的web.py 应用。
3.启动服务
在你的命令行下输入:
- $ python code.py # 使用默认端口 8080
- 或者
- $ python code.py 10000 # 改变端口为 10000
你的web.py 应用已经启动了服务器。通过浏览器访问:http://localhost:8080/ ,会见到”Hello, world!“。
修改默认端口
在启动服务器的时候,如果你不想使用默认端口,你可以使用这样的命令来指定端口号: python code.py 8888。
4. 调试
直接添加一行 web.internalerror = web.debugerror 即可。如下
- if __name__=="__main__":
- web.internalerror = web.debugerror
- app.run()
5. 模板
更多关于 web.py templates 可以访问 http://webpy.org/docs/0.3/templetor.zh-cn
在Python 里面编写HTML 代码是相当累赘的,而在HTML 里嵌入Python 代码则有趣得多。幸运地,web.py 使这过程变得相当容易。
注意:旧版本的web.py 是用Cheetah templates 模板的,你可以继续使用,但官方已不再提供支持。
新建一个 code.py 的 python文件。内容如下:
- import web
- urls = (
- # '/(.*)', 'hello',
- '/hello_1[/]?.*', 'hello_1',
- '/hello_2/(.*)', 'hello_2',
- )
- app = web.application(urls, globals())
- render=web.template.render('templates')
- class hello_1:
- def GET(self):
- return render.index_1()
- class hello_2:
- def GET(self, name):
- return render.index_2("Lisa")
- if __name__ == "__main__":
- app.run()
创建模板
这里,我们先在项目 code.py 同一级目录中新建一个目录(例如 templates )集中存放并用来组织模板文件,便于管理。然后在templates下新建HTML 文件(例如:”index.html“)。这里新建 两个 HTML 文件。 index_1.html 和 index_2.html
index_1.html 文件内容如下:
- <em>Hello</em>, world!
这是一个最简单的html页面代码。
index_2.html 文件内容如下:
- $def with (name)
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Template</title>
- </head>
- <body>
- Hi, $name
- </body>
- </html>
注意上面代码的缩进!
正如你所见的,上面的模板看上去跟这Python 文件很相似,以def with 语句开始,但在关键字前需要添加”$“。
注意:在模板内的变量,如果包含有HTML 标记,以$ 方式引用变量的话,HTML 标记只会以纯文本的显示出来。要想HTML 标记产生效果,可以用$: 引用变量。
使用模板
现在,回到 code.py 文件,在”import web” 的下一行添加:
- render = web.template.render('templates/')
这告诉web.py 在哪里可以搜索得到模板目录。提示:可在render 调用里添加cache = False 使得每次访问页面时都重载模板。
然后再修改使用这个模板的类,在这里 修改 类 hello_1 和 类 hello_2
- class hello_1:
- def GET(self):
- return render.index_1()
- class hello_2:
- def GET(self, name):
- # name = "Lisa"
- return render.index_2("Lisa")
上面的 ”index_1“ 和 “index_2” 是模板的名字,”Lisa“ 是传递过去的参数。
同时修改urls为:
- urls = (
- # '/(.*)', 'hello',
- '/hello_1[/]?.*', 'hello_1',
- '/hello_2/(.*)', 'hello_2',
- )
上面的“/(.*)” 是一个正则表达式。括号里面是要传递的参数。再将GET 方法修改如下:
- def GET(self,name):
- print render.index_2(name)
hello_1 页面调用 hello_1 类,使用 index_1.html 模板。打开 http://localhost:8080/hello_1 ,页面就会打印出 Hello, world
的字样。
hello_2/ 页面调用 hello_2 类,使用 index_2.html 模板,打开 http://localhost:8080/hello_2/,页面就会打印出 Hello, Lisa
的字样。
除此之外还有两种使用模板的方法
- 使用frender直接指定模板文件。GET函数最后两行改为
- render=web.template.frender("templates/index.html")
- return render("Lisa")
- 直接在代码里写出模板文件。GET最后两行改为
- template = "$def with (name)\nHello $name"
- render = web.template.Template(template)
- return render("Lisa")
模板含义
现在解释一下这个 index.html 模板的含义:
- $def with (name)
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Template</title>
- </head>
- <body>
- Hi, $name
- </body>
- </html>
在index.html第一行 $def with (name)表示本模板接受一个名为name的参数,也就是对应index类中return render.index(“Lisa”)中的Lisa。
而render=web.template.render(“templates”)表示创建一个模板对象,模板是存放于templates目录下,然后就可以用所创建的 render 对象来访问相应的模板
比如templates目录下的index.html就是用render.index来表示(实际上是匹配寻找index.*文件,第一个匹配的就认为是所对应的模板文件),如果templates下还有个a目录,a目录下有个pagea.html,那么访问这个pagea模板就要用render.a.pagea的形式了。
页面参数
页面接收的参数可以多于一个,也可以没有,如果不需要参数,则就不需要$def with (name)这样的代码,删除掉这一句,同时修改模板中对name变量的引用,修改index类最后一句为return render.index()就可以了。
如果有参数,那么模板的第一行代码就必须是这个 $def with (…),可以多于一个参数,比如是这样$def with (gname, fname)。
模板下面的那行字改为Hi, $gname $fname。
同时Index类GET返回的时候赋予对应两个参数return render.index(“Lisa”,”Hayes”)。
这样,页面最后显示的是打印出Hi, Lisa Hayes的字样。
另外,模板接受的这个参数也可以是一个元组,比如像下面这样:return render.index((“Lisa”,”Hayes”))
在模板中可以如下以元组方式访问参数数据:Hi, $name[0] $name[1]
模板语法
模板语法与python语法基本一致,主要差别可以从上面的代码中看到,要使用到$符号表明这不是文本而是模板代码。也就是每当用到程序代码、对象的时候就必须用$来与html代码和页面显示文本相区别。
对象赋值
向对象赋值时需要在$与对象名之间留空格,如为一个名为vara的字符串对象赋值apple的代码为$ vara = “apple”。
另外,对象赋值语句必须独占一行,前面或后面有其他代码则会程序出错。
对象引用
引用对象的时候直接使用 $+对象名的形式,如$vara。
另外引用对象时还可以用{}或()将对象进行明确的分组,如$(vara)s就会表示apples,如果没有括号,程序则会把 $varas作为一个整体,也就变成对varas对象的引用而发生错误。另如果像如下定义两个数字型对象:
- $varb = 1
- $varc = 2
然后希望计算两个值的和,如果用$varb+$varc的形式,页面上只会得到1+2而不是3,这时也就需要把两个对象放在括号里,如$(varb+varc)的形式才能得到正确答案3。
注释
模板中支持单行注释,以$#符号开始到行末都是注释内容。
$#This is comment
注释前面可以有其他内容,但是不可以有赋值代码。
如下代码是正确的:Hi $#This is comment
但下面的则会出错:$ vara = “apple” $#This is comment
打印$符号
由于$符号在模板中有特殊用途,所以在页面上输出$时需要进行转义操作,用连续两个$表示在页面上输出一个$符号。
Can you lend me $50?
控制代码(循环、条件判断)
模板中支持for、while、if、elif、else,用法与在python一致,只是控制代码行要以$开始(包括break和continue命令),$开始的代码行中对象不需要在前面再加$符号,同时要注意缩进规则,如:
for 循环:
- $def with (toUser,fromUser,createTime,articleCnt,articles)
- <xml>
- <ToUserName><![CDATA[$toUser]]></ToUserName>
- <FromUserName><![CDATA[$fromUser]]></FromUserName>
- <CreateTime>$createTime</CreateTime>
- <MsgType><![CDATA[news]]></MsgType>
- <ArticleCount>$articleCnt</ArticleCount>
- <Articles>
- $for a in articles:
- <item>
- <Title><![CDATA[$a['title']]]></Title>
- <Description><![CDATA[$a['desc']]]></Description>
- <PicUrl><![CDATA[$a['picUrl']]]></PicUrl>
- <Url><![CDATA[$a['url']]]></Url>
- </item>
- </Articles>
- </xml>
if else判断:
- $if times > max:
- Stop! In the name of love.
- $else:
- Keep on, you can do it.
在for循环中,有一组内置的变量可以使用,非常方便,分别如下所示:
- loop.index: 循环次数计数 (1-开始)
- loop.index0: 循环次数计数(0-开始)
- loop.first: 如果是第一次循环则为True
- loop.last: 如果是最后一次循环则为True
- loop.odd: 如果是第奇数次循环则为True
- loop.even: 如果是第偶数次循环则为True
- loop.parity: 如果循环次数为奇数值为“odd” ,反之为 “even”
- loop.parent: 本循环的外层循环对象
- $for a in ["a", "b", "c", "d"]:
- $loop.index,$loop.index0,$loop.first,$loop.last,$loop.odd,$loop.even,$loop.parity<br/>
将在页面上打印出:
- 1,0,True,False,True,False,odd
- 2,1,False,False,False,True,even
- 3,2,False,False,True,False,odd
- 4,3,False,True,False,True,even
函数-$def
函数定义也是与在python中类似,用def,只是也要在前面加$,代码也要注意$的使用和缩进:
- $def hello(name=""):
- Hello $name!
- $hello("Lisa")
- $def hello(name=""):
- <strong/>Hello $name!</strong>
- $:hello("Lisa")
输出程序代码-$code块
如果想在模板里输入写一段python代码而又不想被$所烦恼,那么可以用到$code块。
页面上输出一段代码而不希望被系统理解为模板程序代码,就需要用到$code命令,比如在模板文件中写入下面一段: