輕量級Python web 框架:web.py

From:https://www.oschina.net/question/5189_4306

Web.py github 地址:https://github.com/webpy/webpyhttps://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 十分鐘創(chuàng)建簡易博客:http://blog.csdn.net/freeking101/article/details/53020728

一個簡單的web.py論壇:http://www.cnblogs.com/russellluo/p/3240564.html


web.py 是一個Python 的web 框架,它簡單而且功能強大。web.py 是公開的,無論用于什么用途都是沒有限制的。而且相當?shù)男∏?,應當歸屬于輕量級的web 框架。但這并不影響web.py 的強大,而且使用起來很簡單、很直接。在實際應用上,web.py 更多的是學術上的價值,因為你可以看到更多web 應用的底層,這在當今“抽象得很好”的web 框架上是學不到的 :) 如果想了解更多web.py,可以訪問web.py 的官方文檔。

先感受一下web.py 的簡單而強大:



上面就是一個基于web.py 的完整的Web 應用。將上面的代碼保存為文件code.py,在命令行下執(zhí)行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 解壓,進入解壓后的文件夾,在命令行下執(zhí)行:python setup.py install,在Linux 等系統(tǒng)下,需要root 的權限,可以執(zhí)行:sudo python setup.py install。

2. URL 處理

對于一個站點來說,URL 的組織是最重要的一個部分,因為這是用戶看得到的部分,而且直接影響到站點是如何工作的,例如:www.baidu.com ,其URLs 甚至是網頁界面的一部分。而web.py 以簡單的方式就能夠構造出一個強大的URLs。

在每個web.py 應用,必須先import web 模塊:

import? web

現(xiàn)在,我們須要告訴web.py URL 如何組織,讓我們以一個簡單例子開始:

urls = (

? '/', 'index'? ? )

在上面的例子中,第一部分是匹配URL的正則表達式,像/、/help/faq、/item/(\d+)等(\d+將匹配數(shù)字)。圓括號表示捕捉對應的數(shù)據(jù)以便后面使用。第二部分是接受請求的類名稱,像index、view、welcomes.hello(welcomes模塊的hello類),或者get_\1。\1?會被正則表達式捕捉到的內容替換,剩下來捕捉的的內容將被傳遞到你的函數(shù)中去。(‘index’)是一個類名,匹配的請求將會被發(fā)送過去。這行表示我們要URL/(首頁)被一個叫index的類處理。

現(xiàn)在我們需要創(chuàng)建一個列舉這些 url 的 application。

app = web.application(urls, globals())

GET 和 POST : 區(qū)別

現(xiàn)在,我們需要編寫index 類。當大部人瀏覽網頁的時候,他們都沒有注意到,瀏覽器是通過HTTP 跟World Wide Web 通信的。通信的細節(jié)不太重要,但要明白一點,用戶是通過URLs(例如 / 或者 /foo?f=1)來請求web 服務器完成一定請求的(例如 GET 或者POST)。

GET 是最普遍的方法,用來請求一個頁面。當我們在瀏覽器里輸入“harvard.edu” 的時候,實際上它是向Web 服務器請求GET ”/“。另一個常見的方法是POST,常用于提交特定類型的表單,比如請求買什么東西。每當提交一個去做什么事情(像使用信用卡處理一筆交易)的請求時,你可以使用POST。這是關鍵,因為GET的URL可以明文傳輸提交的參數(shù)。如果提交的是一些重要的敏感信息,例如用戶名,密碼,則可能被別人抓包獲取到。而 POST 則不會在 URL 上傳輸 提交的信息,POST 是通過表單提交信息。

在我們的web.py 代碼中。我們清晰區(qū)分這兩種方法:

class index:

? ? def GET(self):

? ? ? ? print "Hello, world!"

當接收到一個GET 請求時,上面的GET 方法將會被web.py 調用。好的?,F(xiàn)在,我們只需添加最后一行代碼,讓web.py 啟動網頁應用:

if __name__ == "__main__":

? ? app.run()

當接收到一個GET 請求時,上面的GET 方法將會被web.py 調用。好的?,F(xiàn)在,我們只需添加最后一行代碼,讓web.py 啟動網頁應用:

if __name__ == "__main__":

? ? app.run()

上面告訴web.py 如何配置URLs,以及找尋的類在文件中的全局命名空間。然后為我們啟動上面的應用。

整個 code.py 文件的內容如下:



實際上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模板的,你可以繼續(xù)使用,但官方已不再提供支持。

新建一個?code.py?的 python文件。內容如下:


使用模板

現(xiàn)在,回到 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“ 是傳遞過去的參數(shù)。

同時修改urls為:

urls = (

? ? # '/(.*)', 'hello',

? ? '/hello_1[/]?.*', 'hello_1',

? ? '/hello_2/(.*)', 'hello_2',

)

上面的“/(.*)” 是一個正則表達式。括號里面是要傳遞的參數(shù)。再將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?的字樣。



除此之外還有兩種使用模板的方法

???? 1.使用frender直接指定模板文件。GET函數(shù)最后兩行改為

render=web.template.frender("templates/index.html")

? return render("Lisa")

?? 2. 直接在代碼里寫出模板文件。GET最后兩行改為

template = "$def with (name)\nHello $name"

? render = web.template.Template(template)

? return render("Lisa")

模板含義

現(xiàn)在解釋一下這個 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的參數(shù),也就是對應index類中return render.index(“Lisa”)中的Lisa。

而render=web.template.render(“templates”)表示創(chuàng)建一個模板對象,模板是存放于templates目錄下,然后就可以用所創(chuàng)建的 render 對象來訪問相應的模板

比如templates目錄下的index.html就是用render.index來表示(實際上是匹配尋找index.*文件,第一個匹配的就認為是所對應的模板文件),如果templates下還有個a目錄,a目錄下有個pagea.html,那么訪問這個pagea模板就要用render.a.pagea的形式了。

頁面參數(shù)

頁面接收的參數(shù)可以多于一個,也可以沒有,如果不需要參數(shù),則就不需要$def with (name)這樣的代碼,刪除掉這一句,同時修改模板中對name變量的引用,修改index類最后一句為return render.index()就可以了。

如果有參數(shù),那么模板的第一行代碼就必須是這個 $def with (…),可以多于一個參數(shù),比如是這樣$def with (gname, fname)。

模板下面的那行字改為Hi, $gname $fname。

同時Index類GET返回的時候賦予對應兩個參數(shù)return render.index(“Lisa”,”Hayes”)。

這樣,頁面最后顯示的是打印出Hi, Lisa Hayes的字樣。

另外,模板接受的這個參數(shù)也可以是一個元組,比如像下面這樣:return render.index((“Lisa”,”Hayes”))

在模板中可以如下以元組方式訪問參數(shù)數(shù)據(jù):Hi, $name[0] $name[1]

模板語法

模板語法與python語法基本一致,主要差別可以從上面的代碼中看到,要使用到$符號表明這不是文本而是模板代碼。也就是每當用到程序代碼、對象的時候就必須用$來與html代碼和頁面顯示文本相區(qū)別。

對象賦值

向對象賦值時需要在$與對象名之間留空格,如為一個名為vara的字符串對象賦值apple的代碼為$ vara = “apple”。

另外,對象賦值語句必須獨占一行,前面或后面有其他代碼則會程序出錯。

對象引用

引用對象的時候直接使用 $+對象名的形式,如$vara。

另外引用對象時還可以用{}或()將對象進行明確的分組,如$(vara)s就會表示apples,如果沒有括號,程序則會把 $varas作為一個整體,也就變成對varas對象的引用而發(fā)生錯誤。另如果像如下定義兩個數(shù)字型對象:

$varb = 1

$varc = 2

然后希望計算兩個值的和,如果用$varb+$varc的形式,頁面上只會得到1+2而不是3,這時也就需要把兩個對象放在括號里,如$(varb+varc)的形式才能得到正確答案3。

注釋

模板中支持單行注釋,以$#符號開始到行末都是注釋內容。

$#This is comment

注釋前面可以有其他內容,但是不可以有賦值代碼。

如下代碼是正確的:Hi $#This is comment

但下面的則會出錯:$ vara = “apple” $#This is comment

打印$符號

由于$符號在模板中有特殊用途,所以在頁面上輸出$時需要進行轉義操作,用連續(xù)兩個$表示在頁面上輸出一個$符號。

Can you lend me $50?

控制代碼(循環(huán)、條件判斷)

模板中支持for、while、if、elif、else,用法與在python一致,只是控制代碼行要以$開始(包括break和continue命令),$開始的代碼行中對象不需要在前面再加$符號,同時要注意縮進規(guī)則,如:

for 循環(huán):



if else判斷:

$if times > max:

? ? Stop! In the name of love.

$else:

? ? Keep on, you can do it.

在for循環(huán)中,有一組內置的變量可以使用,非常方便,分別如下所示:

loop.index: 循環(huán)次數(shù)計數(shù) (1-開始)

loop.index0: 循環(huán)次數(shù)計數(shù)(0-開始)

loop.first: 如果是第一次循環(huán)則為True

loop.last: 如果是最后一次循環(huán)則為True

loop.odd: 如果是第奇數(shù)次循環(huán)則為True

loop.even: 如果是第偶數(shù)次循環(huán)則為True

loop.parity: 如果循環(huán)次數(shù)為奇數(shù)值為“odd” ,反之為 “even”

loop.parent: 本循環(huán)的外層循環(huán)對象


$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,odd2,1,False,False,False,True,even3,2,False,False,True,False,odd4,3,False,True,False,True,even


函數(shù)-$def

函數(shù)定義也是與在python中類似,用def,只是也要在前面加$,代碼也要注意$的使用和縮進:

$def hello(name=""):

Hello $name!

函數(shù)調用也是用$加函數(shù)名的形式:

$hello("Lisa")

當然,定義函數(shù)時也可以與html代碼混編:

$def hello(name=""):

Hello $name!

但是調用的時候需要在函數(shù)名前用$:前綴,否則html代碼將以plain text形式打印到頁面上。

$:hello("Lisa")

輸出程序代碼-$code塊

如果想在模板里輸入寫一段python代碼而又不想被$所煩惱,那么可以用到$code塊。

頁面上輸出一段代碼而不希望被系統(tǒng)理解為模板程序代碼,就需要用到$code命令,比如在模板文件中寫入下面一段:

$code:

? ? x=10

? ? def print_num(num):

? ? return "num is %d" % num

然后再加上下面代碼:

$print_num(x)

<br/>

$x

這里就用在$code塊中定義的print_num函數(shù)以x變量為參數(shù)在頁面上輸出一行:num is 10

然后下一行直接引用x變量,直接在頁面上輸出數(shù)字10。

$var

$var命令可以在模板中定義變量,在其他地方引用此模板對象的時候可以訪問此定義的變量。

比如我們可以在index.html中添加如下一行:$var vara: this is vara

表示定義了一個名為vara的變量,變量值是字符串this is vara。

把index的GET函數(shù)改為:

def GET(self):

? ? render=web.template.render("templates")

? ? return render.index("Lisa", "Hayes").vara

那么結果顯示在頁面上的就是this is vara這句話。要注意一點的是,這種變量是字符串,即便如下定義變量:$var vara: 0

Vara也并不是數(shù)字0,如果把GET函數(shù)最后改成:return render.index(“Lisa”, “Hayes”).vara+1

會導致程序出錯。如果希望得到期望中的結果1,則需要如下形式代碼:return int(render.index(“Lisa”, “Hayes”).vara)+1

builtins and globals

在模板中,用戶可以直接使用python的內建函數(shù)和變量,寫函數(shù)變量包括range, min, max 以及 True 和 False等。 除此之外,如果希望在模板中使用其他的非內建功能,就需要一點特殊操作。要在創(chuàng)建render的時候顯式指定所需要的功能函數(shù)。


import web

import markdown

globals = {'markdown': markdown.markdown}

render =web.template.render('templates', globals=globals)

這樣,在模板中就可以用$markdown來引用markdown.markdown了。同樣,也可以用這種辦法來禁用builtins

# disable all builtins

render = web.template.render('templates', builtins={})

模板復用

當多個頁面有著相同的結構框架的時候,為每一個頁面單獨維護一個模板就顯得比較麻煩,web.py提供了一種簡易的解決方法。

這時候就要用到創(chuàng)建render時使用base參數(shù):

render=web.template.render("templates",base="layout")

return render.index("Lisa", "Hayes")

這個layout表示要以templates下的layout.html模板為通用模板框架。因此我們還要在templates目錄下新建一個layout.html文件,寫下如下代碼:

$def with (content)

? ? <!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>Layout</title>

? ? </head>

? ? <body>

? ? ? ? $:content

? ? </body>

</html>

可以看到,這個模板文件必須是有一個參數(shù)content。然后修改index.html,只保留如下代碼,其他刪掉:

$def with(gname, fname)

? ? Hi, $(gname) $(fname)

運行程序,頁面上打印Hi, Lisa Hayes,查看代碼會發(fā)現(xiàn)最終代碼就是index.html和layout.html合并在一起的結果,index.html中的內容被嵌入到layout.html中的$:content處。

在layout.html模板中還可以引用index.html中定義的var變量,這為程序帶來了更多的靈活性,比如我們希望在不同的頁面在使用同一個layout模板的時候能有不同的title,可以在使用layout的模板中定義如下一個var變量:$var title:This is index.html

然后在layout.html中的title處修改為:$content.title

這樣,訪問index.html時顯示在瀏覽器上的title就是This is index.html,而不是原來的Layout了。

在模板中使用python代碼模塊

在默認狀態(tài)下,在模板中是不能直接調用其他python代碼模塊文件中的程序的,必須做一些額外的操作。

首先,我們新建一個模塊,叫module1.py,在里面寫一個函數(shù):

def hello_from_m1(name=""):

? ? return "hello %s, this is module1" % name

在main.py里導入module1:import module1

并且修改GET函數(shù)中創(chuàng)建render的代碼為:

def GET(self):

? ? render=web.template.render("templates",base="layout",globals={"m1":module1})

? ? return render.index("Lisa")

globals參數(shù)中傳遞的是一個字典,key以字符串表示模塊在模板中使用時的名稱,value部分就是這個要在模塊中使用的模塊或對象的真實名稱了。

最后在要使用此模塊的模板中就可以用$m1來引用此模塊了。比如在index.html中添加下面一行代碼:$m1.hello_from_m1(gname)

就會調用module1中的hello_from_m1函數(shù),在頁面上打印出:hello Lisa, this is module1

在web.py模板中使用jQuery

在jQuery中$也是一個關鍵字,這樣的話如果在模板中使用jQuery就會沖突,這時候只需要用$做一下轉義就可以了,比如:

<script type="text/javascript">

$(document).ready(function()

{

? ? alert("It works.");

});

</script>


6. 數(shù)據(jù)庫

Web.py 更多關于數(shù)據(jù)庫的操作:http://webpy.org/cookbook/index.zh-cn

注意:在你開始連接數(shù)據(jù)庫之前,請先安裝正確的數(shù)據(jù)庫驅動。比如 MySQLdb、psycopg2。如果需要嘗試連接 池(database pool)功能,還得裝下DBUtils。這幾個模塊都可以通過easy_install 或者 pip 來安裝。

連接數(shù)據(jù)庫:

import web

db = web.database(dbn='postgres', db='mydata', user='dbuser', pw='')

操作 數(shù)據(jù)庫 示例

select查詢# 查詢表entries = db.select('mytable')? ? #where條件myvar = dict(name="Bob")results = db.select('mytable', myvar,where="name = $name")results = db.select('mytable',where="id>100")# 查詢具體列results = db.select('mytable', what="id,name")#orderbyresults = db.select('mytable',order="post_date DESC")#groupresults = db.select('mytable',group="color")#limitresults = db.select('mytable',limit=10)#offsetresults = db.select('mytable',offset=10)更新db.update('mytable',where="id = 10", value1 ="foo")刪除db.delete('mytable',where="id=10")復雜查詢#countresults = db.query("SELECT COUNT(*) AS total_users FROM users")print results[0].total_users#joinresults = db.query("SELECT * FROM entries JOIN users WHERE entries.author_id = users.id")# 防止SQL注入可以這么干results = db.query("SELECT * FROM users WHERE id=$id", vars={'id':10})多數(shù)據(jù)庫操作 (web.py大于0.3)db1 = web.database(dbn='mysql', db='dbname1',user='foo')db2 = web.database(dbn='mysql', db='dbname2',user='foo')print db1.select('foo',where='id=1')print db2.select('bar',where='id=5')事務t = db.transaction()try:? ? db.insert('person',name='foo')? ? db.insert('person',name='bar')except:? ? t.rollback()raiseelse:? ? t.commit()# Python2.5+ 可以用withfrom__future__importwith_statementwithdb.transaction():? ? db.insert('person',name='foo')? ? db.insert('person',name='bar')

現(xiàn)在,在數(shù)據(jù)庫里創(chuàng)建一個簡單的表:

CREATE TABLE todo (

? id serial primary key,

? title text,

? created timestamp default now(),

? done boolean default 'f'

);

/* 初始化一行 */

INSERT INTO todo (title) VALUES ('Learn web.py');

回到 code.py,修改GET 方法如下:

defGET(self):

todos = db.select('todo')

printrender.index(todos)

修改urls 變量:

urls = (

'/','index')

重新編輯index.html 文件如下:

$defwith(todos)

    $fortodointodos:$todo.title

現(xiàn)在,可以訪問”/“,如果顯示”Learn web.py“,則祝賀你成功了!

現(xiàn)在,再讓我們看看如何向數(shù)據(jù)庫寫入。在index.html 文件的尾部添加如下內容:

<form method="post" action="add">

? <p>

? ? ? <input type="text" name="title" />

? ? ? <input type="submit" value="Add" />

? </p>

</form>

在code.py 里添加一個類:

class add:

? ? def POST(self):

? ? ? ? i = web.input()

? ? ? ? n = db.insert('todo', title=i.title)

? ? ? ? web.seeother('/')

web.input?使你能夠方便地訪問用戶通過表單提交上來的變量。db.insert?用于向數(shù)據(jù)庫的 “todo” 表插入數(shù)據(jù),并且返回新插入行的ID。web.seeother?用于重轉向到”/“。

提示:對于數(shù)據(jù)庫的操作,還有db.transact(),?db.commit(),?db.rollback(),db.update()。

在web.py 里,還有web.input,web.query?和其它的函數(shù),返回”Storage objects”,可以像字典型類(dictionaries) 的使用。

使用 Web.py 搭建一個測試網站案例

Web.py Form庫文檔 和 示例代碼 :http://webpy.org/form

參考http://blog.csdn.net/freeking101/article/details/76148434這篇文章改寫成 Web.py 搭建測試網站

先看 官網一個使用 Form 表單的示例(code.py):


formtest.html?代碼如下:

$def with (form)

<div align="center">

<form name="main" method="post">

$if not form.valid: <p class="error">Try again, AmeriCAN:</p>

$:form.render()

<input type="submit" />

</form>

<div>

Linux 下運行結果



然后根據(jù)上面內容開始改寫 自己的網站


原文參考:https://blog.csdn.net/freeking101/article/details/53020865

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 22年12月更新:個人網站關停,如果仍舊對舊教程有興趣參考 Github 的markdown內容[https://...
    tangyefei閱讀 35,393評論 22 257
  • 在 Python 中寫 HTML 不是聰明的選擇,相反在 HTML 中寫 Python 則有趣的多。幸運的是,we...
    hxzqlh閱讀 8,315評論 1 18
  • Web.py 一、Templetor模板對象 (1)模板系統(tǒng)使用方式 在工程同級目錄下創(chuàng)建templates文件夾...
    凜0_0閱讀 778評論 0 0
  • Web框架之Django: (1)簡介: Django是一個由Python寫成開源的重量級Web應用框架,采用MT...
    老肖閱讀 3,160評論 0 18
  • 《天涼好個秋》/鳳雅文卿 看盡千篇文抒淚, 誰聞夜挑燭光寒? 悲涼卻在天涯外, 一籠紗窗月影殘。 《思雨》/鳳雅文...
    鳳雅文卿閱讀 317評論 0 0

友情鏈接更多精彩內容