python網路編程學習筆記(10):webpy架構

來源:互聯網
上載者:User
django和webpy都是python的web開發架構。Django的主要目的是簡便、快速的開發資料庫驅動的網站。它強調代碼複用,多個組件可以很方便的以“外掛程式”形式服務於整個架構,Django有許多功能強大的第三方外掛程式,你甚至可以很方便的開發出自己的工具包。這使得Django具有很強的可擴充性。它還強調快速開發和DRY(Do Not Repeat Yourself)原則。webpy小巧,簡單,實用,可以快速的完成簡單的web頁面。這雷根據webpy Cookbook簡要的介紹一下webpy架構,更加詳細請見http://webpy.org/cookbook/index.zh-cn。

一、安裝與開發

web.py下載地址:http://webpy.org/static/web.py-0.33.tar.gz。解壓並拷貝web檔案夾到你的應用程式目錄下。或者,為了讓所有的應用程式都可以使用,運行:

代碼如下:


python setup.py install

注意: 在某些類unix系統上你可能需要切換到root使用者或者運行:

代碼如下:


sudo python setup.py install

也可以直接把裡面的WEB檔案夾放site-packages 。
web.py 內建了web伺服器,代碼寫完後,將其儲存,例如檔案名稱為mywebpy.py,可以用下面的方法來啟動伺服器:

代碼如下:


python mywebpy.py


開啟你的瀏覽器輸入 http://localhost:8080/ 查看頁面。 若要制定另外的連接埠,使用 python mywebpy.py 1234。

二、URL 處理

任何網站最重要的部分就是它的URL結構。你的URL並不僅僅只是訪問者所能看到並且能發給朋友的。它還規定了你網站啟動並執行心智模型。在一些類似del.icio.us的流行網站 , URL甚至是UI的一部分。 web.py使這類強大的URL成為可能。

代碼如下:


urls = (
'/', 'index'
)

第一部分是匹配URL的Regex,像/、/help/faq、/item/(\d+)等(\d+將匹配數字)。圓括弧表示捕捉對應的資料以便後面使用。第二部分是接受請求的類名稱,像index、view、welcomes.hello (welcomes模組的hello類),或者get_\1。\1 會被Regex捕捉到的內容替換,剩下來捕捉的的內容將被傳遞到你的函數中去。這行表示我們要URL/(首頁)被一個叫index的類處理。現在我們需要建立一個列舉這些url的application。
app = web.application(urls, globals())
這會告訴web.py去建立一個基於我們剛提交的URL列表的application。這個application會在這個檔案的全域命名空間中尋找對應類。
一般來說,在每個應用的最頂部,你通常會看到整個URL調度模式被定義在元組中:

代碼如下:


urls = (
"/tasks/?", "signin",
"/tasks/list", "listing",
"/tasks/post", "post",
"/tasks/chgpass", "chgpass",
"/tasks/act", "actions",
"/tasks/logout", "logout",
"/tasks/signup", "signup"
)

這些元組的格式是: URL路徑, 處理類 。

你可以利用強大的Regex去設計更靈活的URL路徑。比如 /(test1|test2) 可以捕捉 /test1 或 /test2。要理解這裡的關鍵,匹配是依據URL路徑的。比如下面的URL:
http://localhost/myapp/greetings/hello?name=Joe
這個URL的路徑是 /myapp/greetings/hello。web.py會在內部給URL路徑加上和$ ,這樣 /tasks/ 不會匹配 /tasks/addnew。URL匹配依賴於“路徑”,所以不能這樣使用,如: /tasks/delete?name=(.+) ,?之後部分表示是“查詢”,並不會被匹配。閱讀URL組件的更多細節,請訪問web.ctx。

你可以捕捉URL的參數,然後用在處理類中:
/users/list/(.+), "list_users"
在 list/後面的這塊會被捕捉,然後作為參數被用在GET或POST:

代碼如下:


class list_users:
def GET(self, name):
return "Listing info about user: {0}".format(name)

你可以根據需要定義更多參數。同時要注意URL查詢的參數(?後面的內容)也可以用web.input()取得。

三、hello world

現在我們需要來寫index類。雖然大多數人只會看看,並不會注意你的瀏覽器在使用用於與全球資訊網通訊的HTTP語言。具體的細節並不重要,但是要理解web訪問者請求web伺服器去根據URL(像/、/foo?f=1)執行一個合適的函數(像GET、POST)的基本思想。GET用於請求網頁文本。當你在瀏覽器輸入harvard.edu,它會直接存取Harvard的web伺服器,去GET /。 POST經常被用在提交form,比如請求買什麼東西。每當提交一個去做什麼事情(像使用信用卡處理一筆交易)的請求時,你可以使用POST。這是關鍵,因為GET的URL可以被搜尋引擎索引,並通過搜尋引擎訪問。雖然大部分頁面你希望被索引,但是少數類似訂單處理的頁面你是不希望被索引的。
在我們web.py的代碼中,我們將這兩個方法明確區分:

代碼如下:


class index:
def GET(self):
return "Hello, world!"

當有人用GET請求/時,這個GET函數隨時會被web.py調用。
好了,限制我們只需要最後一句就寫完了。這行會告訴web.py開始提供web頁面:

代碼如下:


if __name__ == "__main__": app.run()

這會告訴web.py為我們啟動上面我們寫的應用。
於是將上面的代碼完整列出如下:

代碼如下:


import web
urls = (
'/', 'index'
)

class index:
def GET(self):
return "Hello, world!"

if __name__ == "__main__":
app = web.application(urls, globals())
app.run()

儲存為hello.py,運行後顯示:
http://0.0.0.0:8080/
在瀏覽器中輸入http://127.0.0.1:8080,就會出現hello world!頁面。

四、模板

給模板建立一個目錄(命名為 templates),在該目錄下建立一個以 .html 結尾的檔案,這裡存為index.html,內容如下:

代碼如下:


Hello, world!

你也可以在模板中使用 web.py 模板支援代碼:

代碼如下:


$def with (name)
$if name:
I just wanted to say hello to $name.
$else:
Hello, world!

如上,該模板看起來就像 python 檔案一樣,除了頂部的 def with (表示從模板將從這後面取值)和總是位於程式碼片段之前的$。當前,template.py 首先請求模板檔案的首行 $def 。當然,你要注意 web.py 將會轉義任何用到的變數,所以當你將name的值設為是一段HTML時,它會被轉義顯示成純文字。如果要關閉該選項,可以寫成 $:name 來代替 $name。

在code.py第一行之下添加:

代碼如下:


render = web.template.render('templates/')

這會告訴web.py到你的模板目錄中去尋找模板。然後把 index.GET改成: 告訴 web.py 在你的模板目錄下尋找模板檔案。修改 index.GET :

代碼如下:


name = 'Bob'
return render.index(name)

完整代碼為:

代碼如下:


##@小五義
import web
render = web.template.render('templates/')
urls = (
'/', 'index'
)

class index:
def GET(self):
name='Bob'
return render.index(name)
#return "Hello, world!"

if __name__ == "__main__":
app = web.application(urls, globals())
app.run()

訪問網站它將顯示 I just wanted to say hello to Bob。

但是如果我們想讓使用者自行輸入他的名字,如下:

代碼如下:


i = web.input(name=None)
return render.index(i.name)

訪問 / 將顯示 hello world,訪問 /?name=Joe 將顯示 I just wanted to say hello to Joe。
URL 的後面的 ? 看起來不好看,修改下 URL 配置:
'/(.*)', 'index'

然後修改下 GET:

代碼如下:


def GET(self, name):
return render.index(name)

完整代碼為:

代碼如下:


##@小五義
import web
render = web.template.render('templates/')
urls = (
'/(.*)', 'index'
)

class index:
def GET(self,name):
i=web.input(name=None)
return render.index(name)
#return "Hello, world!"

if __name__ == "__main__":
app = web.application(urls, globals())
app.run()

現在訪問http://127.0.0.1:8080/TOM ,它會顯示I just wanted to say hello to TOM. 如果訪問http://127.0.0.1:8080/,它會顯示Hello, world!

五、表單

1、簡介

表單包括Textbox、Password 、Textarea 、Dropdown、Radio、Checkbox、Button具體使用及樣式如下:

代碼如下:


login = form.Form(
form.Textbox('username'),
form.Password('password'),
form.Password('password_again'),

form.Button('Login'),
form.Checkbox('YES'),
form.Checkbox('NO'),
form.Textarea('moe'),
form.Dropdown('SEX', ['man', 'woman']),
form.Radio('time',['2012-01-01','20120101']),
validators = [form.Validator("Passwords didn't match.", lambda i: i.password == i.password_again)]
)

顯現在頁面中:

2、輸入屬性
如:

代碼如下:


form.textbox("firstname",
form.notnull, #put validators first followed by optional attributes
class_="textEntry", #gives a class name to the text box -- note the underscore
pre="pre", #directly before the text box
post="post", #directly after the text box
description="please enter your name", #describes field, defaults to form name ("firstname")
value="bob", #default value
id="nameid", #specify the id
)

3、例子:

代碼如下:


##code.py
##@小五義
import web,os
from web import form

render = web.template.render("d:/webpy/templates")##這裡仿照http://webpy.org/form#example最初使用了相對路徑templates/,但總是發生找不到formtest的錯誤,於是搜尋後,發現換成絕對路徑可以解決這一問題。

urls = (
'/', 'index',

)
app = web.application(urls, globals())
login = form.Form(
form.Textbox('username'),
form.Password('password'),
form.Password('password_again'),

form.Button('Login'),
form.Checkbox('YES'),
form.Checkbox('NO'),
form.Textarea('moe'),
form.Dropdown('SEX', ['man', 'woman']),
form.Radio('time',['2012-01-01','20120101']),
validators = [form.Validator("Passwords didn't match.", lambda i: i.password == i.password_again)]

)


class index:

def GET(self):
f=login()
return render.formtest(f)
def POST(self):
f=login()
if not f.validates():
return render.formtest(f)

else:
return "HAHA!"

if __name__ == "__main__":
web.internalerror = web.debugerror

app.run()

d:/webpy/templates檔案夾下存放formtest.html檔案,檔案代碼如下:

代碼如下:


$def with (form)


運行code.py,然後在瀏覽器中瀏覽頁面如下:



填寫表格後,如果兩次password相同,那麼會顯示HAHA!,否則顯示Try again, Passwords didn't match:。

六、資料庫

1、資料庫的串連
在開始使用資料庫之前,確保已經安裝了合適的資料庫訪問庫。比如對於MySQL資料庫,使用 MySQLdb ,對於Postgres資料庫使用psycopg2。
建立一個資料庫物件:db = web.database(dbn='postgres', user='username', pw='password', db='dbname')
2、資料庫讀取
例,在資料庫test中有一個表testtable,欄位是name,在上面code.py中進行修改,如果login成功,那麼列出test表中的內容。

code.py

代碼如下:


##@小五義
import web,os
from web import form
db = web.database(dbn='postgres', user='postgres', pw='password', db='test')
render = web.template.render("d:/webpy/templates")
urls = (
'/', 'index',

)
app = web.application(urls, globals())
login = form.Form(
form.Textbox('username'),
form.Password('password'),
form.Password('password_again'),
form.Button('Login'),
form.Checkbox('YES'),
form.Checkbox('NO'),
form.Textarea('moe'),
form.Dropdown('SEX', ['man', 'woman']),
form.Radio('time',['2012-01-01','20120101']),
validators = [form.Validator("Passwords didn't match.", lambda i: i.password == i.password_again)]

)

class index:

def GET(self):
f=login()
return render.formtest(f)
def POST(self):
f=login()
if not f.validates():
return render.formtest(f)

else:
testtables = db.select('testtable')
return render.index(testtables)


if __name__ == "__main__":
web.internalerror = web.debugerror

app.run()

##index.html

代碼如下:


$def with (testtables)


    $for testtable in testtables:
  • $testtable.name


當login正確後,會列出testtable表中name欄位的值。

3、資料庫寫入
如將上面的FORM表中的user加入到testtable表name欄位中,很簡單,只需要在上面的代碼中加入一句:n=db.insert('voa',filename=f['username'].value)。
現在,對code.py代碼進行修改後,當表單填寫正確後,會將username加入到testtable表中,完整代碼如下:

代碼如下:


##@小五義
import web,os
from web import form
db = web.database(dbn='postgres', user='postgres', pw='password', db='bbstime')
render = web.template.render("d:/webpy/templates")
urls = (
'/', 'index',

)
app = web.application(urls, globals())
login = form.Form(
form.Textbox('username'),
form.Password('password'),
form.Password('password_again'),
form.Button('Login'),
form.Checkbox('YES'),
form.Checkbox('NO'),
form.Textarea('moe'),
form.Dropdown('SEX', ['man', 'woman']),
form.Radio('time',['2012-01-01','20120101']),
validators = [form.Validator("Passwords didn't match.", lambda i: i.password == i.password_again)]

)

class index:

def GET(self):
f=login()
return render.formtest(f)
def POST(self):
f=login()
if not f.validates():
return render.formtest(f)

else:
n=db.insert('voa',filename=f['username'].value)
voas = db.select('voa')
return render.index(voas)
if __name__ == "__main__":
web.internalerror = web.debugerror
app.run()

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.