TurboGears(一)此刻,你可能已經(jīng)看了“教程”或“關(guān)于 TurboGears”。就算沒(méi)看也沒(méi)關(guān)系。這份指南也是個(gè)很好的開(kāi)始。 本指南介于教程和參考文檔之間。就是說(shuō)既不過(guò)多的糾纏于細(xì)節(jié)也不指望成為一份教程。 這里不介紹如何安裝 TurboGears,具體的安裝指令官方網(wǎng)站的“下載”上介紹的有。這里同樣也不介紹 Python 的相關(guān)知識(shí),了解它有很多其它的渠道。 1、tg-admin tg-admin 是 TurboGears 的一個(gè)命令行工具,它有幾個(gè)子命令,它同它的子命令一起可以讓你快速的創(chuàng)建一個(gè)新項(xiàng)目、交互式的以面向?qū)ο笥蟹绞骄S護(hù)你的數(shù)據(jù)庫(kù)等等。 如果你在命令行上運(yùn)行 tg-admin,會(huì)得到一個(gè)它的子命令的列表以及簡(jiǎn)單的功能介紹:
xxx@x[~]$ tg-admin
這里我們只是簡(jiǎn)單的使用“quickstart”開(kāi)啟一個(gè)項(xiàng)目:
tg-admin quickstart
它會(huì)提示你輸入項(xiàng)目名稱(chēng)等,輸入你喜歡的名字,回車(chē)就可以了:
Enter project name: gs Enter package name [gs]: Do you need Identity (usernames/passwords) in this project? [no] Selected and implied templates: TurboGears#tgbase tg base template TurboGears#turbogears web framework
運(yùn)行完后,當(dāng)前目錄下會(huì)出現(xiàn)一個(gè)以你輸入的項(xiàng)目名稱(chēng)命名的目錄,cd 進(jìn)去,會(huì)發(fā)現(xiàn) TurboGears 已經(jīng)為你自動(dòng)生成了一些代碼,使用 TurboGears 開(kāi)發(fā)的過(guò)程其實(shí)就是對(duì)這些代碼修修補(bǔ)補(bǔ)、加上你自己代碼的過(guò)程了。 2、開(kāi)啟服務(wù)器 一旦運(yùn)行完“quickstart”,你就可以發(fā)動(dòng) CherryPy 的內(nèi)置服務(wù)器了:
xxx@x[pythonExc]$ cd gs/ xxx@x[gs]$ ls dev.cfg gs.egg-info sample-prod.cfg setup.pyc gs README.txt setup.py start-gs.py xxx@x[gs]$ python start-gs.py 2006-06-01 17:44:10,606 cherrypy.msg INFO CONFIG: Server parameters: ......
在瀏覽器中打開(kāi)http://localhost:8080,你就會(huì)看到一個(gè)簡(jiǎn)單的歡迎頁(yè)面。要停止服務(wù)器的話,可以按 Ctrl-C 組合鍵。 3、配置 “quickstart”會(huì)為你創(chuàng)建一些配置文件,這些配置文件以”.cfg“結(jié)尾。
xxx@x[gs]$ ls *.cfg dev.cfg sample-prod.cfg xxx@x[gs]$ ls gs/config/*.cfg gs/config/app.cfg gs/config/log.cfg xxx@x[gs]$
從它們的名字可以猜出: dev.cfg 是為開(kāi)發(fā)過(guò)程準(zhǔn)備的一套配置,sample-prod.cfg 則是正式發(fā)布你的程序時(shí)用的配置文件 prod.cfg 的一個(gè)樣例。dev.cfg 和 prod.cfg 同時(shí)要用到的配置則應(yīng)該寫(xiě)進(jìn) gs/config/app.cfg。gs/config/log.cfg 通常開(kāi)發(fā)過(guò)程中才用到,但一些特殊的處理以及格式定義可以寫(xiě)在這兒。 啟動(dòng)服務(wù)器時(shí),start-xxx.py 腳本會(huì)先看當(dāng)前目錄下有沒(méi)有 setup.py 文件,如果有的話就使用 dev.cfg 中的配置,否則的話,使用 prod.cfg 中的配置。 你也可以從命令行指定使用哪個(gè)配置文件:
xxx@x[gs]$ python start-gs.py sample-prod.cfg
打開(kāi) http://localhost: 8080,會(huì)看到服務(wù)器正常工作了。(注:我現(xiàn)在還不能確信是不是這樣從命令行指定配置文件,但上面的命令在我這里可以工作。究竟該怎么做,我們后來(lái)再求證。) 4、TurboGears 工作原理示意圖
很多盒子和箭頭!它展示了一個(gè) TurboGears 應(yīng)用程序的所有組成部分。大部分都是 TurboGears 自帶的,你只需要關(guān)心淺紫色盒子表示的部分就行了。
你只要修改這三部分代碼就可以了。這也就是 TurboGears 被稱(chēng)為 MVC 框架的由來(lái)。 除此之外,你還會(huì)看到一些其它顏色的盒子。其中,CherryPy 是一種非常 pythonic 的、面向?qū)ο?web 開(kāi)發(fā)框架,我的這個(gè)網(wǎng)站就是基于它寫(xiě)的。作為 TurboGears 最主要的部件之一,它主要負(fù)責(zé)提供 web 服務(wù),即完成 controller 的功能。SQLObject 定義 model,Kid 用來(lái)編寫(xiě)模板,MochiKit是一套 AJAX 庫(kù),和 Kid 一起完成 view 功能。
TurboGears(三)5、CherryPy發(fā)布 請(qǐng)參考這里,或 CherryPy 官方文檔。 6、自動(dòng)單元測(cè)試 TurboGears 使用 Nose 完成此項(xiàng)功能。 單元測(cè)試這個(gè)概念,此前我從未接觸過(guò),一時(shí)之間難以弄明白,所以暫時(shí)隔過(guò)去,不然的話對(duì) TurboGears 的學(xué)習(xí)又會(huì)就此停頓。 以下是 Google 到的一些資料,留到后來(lái)仔細(xì)閱讀。
7、參數(shù)有效性驗(yàn)證及類(lèi)型轉(zhuǎn)換 TurboGears 提供了一個(gè)簡(jiǎn)便的工具 FormEncode,來(lái)驗(yàn)證傳入的方法參數(shù)是否有效以及將這些參數(shù)從字符串轉(zhuǎn)換為其它合適的 Python 類(lèi)型。這里是一個(gè)簡(jiǎn)單的例子:
import turbogears from turbogears import validators, expose, validate
傳遞給 turbogears.expose 的 validators 字典意思是說(shuō),使用 Int 校驗(yàn)器來(lái)驗(yàn)證參數(shù)值是否有效。如果無(wú)效,就會(huì)得到一個(gè) tg_errors,否則的話,tg_errors 的值為 None,你就可以確認(rèn)參數(shù)值是 Int 類(lèi)型了。 如果驗(yàn)證失敗,tg_errors 將會(huì)是一個(gè)字典類(lèi)型的值,查看 tg_errors[ ‘value‘ ]的話,你會(huì)得到一個(gè) ‘Invalid‘ 異常對(duì)象。Invalid 異常對(duì)象提供了一個(gè)用戶(hù)友好的錯(cuò)誤信息。 TurboGears 有一個(gè)非常強(qiáng)大和靈活的的錯(cuò)誤處理機(jī)制,允許你傳遞錯(cuò)誤給不同的方法,以便你的 controller 方法可以始終接收到良好的輸入。 所有的驗(yàn)證器都被導(dǎo)入了 turbogears.validators 模塊。你可以查閱這個(gè)模塊或者 FormEncode 驗(yàn)證器模塊來(lái)看一下都有哪些具體的驗(yàn)證器可用。 還有些比較高級(jí)的內(nèi)容,需要的時(shí)候可以查閱 FormEncode 的官方網(wǎng)站。
TurboGears(四)8、如何選擇 View 模板 單獨(dú)用 CherryPy 的話,你可以返回一個(gè)字符串給瀏覽器。這很好,但更多時(shí)候你想返回的是一個(gè)完整的頁(yè)面。在 TurboGears 中,你則可以將一個(gè)字典型的變量返回給 Kid 模板,用這些變量的值填充模板中相應(yīng)的變量。 在使用 quickstart 創(chuàng)建的項(xiàng)目中,你的模板文件位于 packagename.templates 中。它們以 .kid 結(jié)尾,但具體指定時(shí),你可以省略這個(gè)擴(kuò)展名。所以如果你想使用一個(gè)叫 welcome 的模板,你可以這樣指定:
template = ‘packagename.templates.welcome‘
在我的例子中,如果我打開(kāi) ‘gs/controllers.py‘,會(huì)看到這么幾行:
class Root(controllers.RootController): @expose(template="gs.templates.welcome") def index( self, value = ‘0‘ ):
這可以看作一個(gè)更加具體的如何指定所要使用的模板文件的例子。 返回的字典中應(yīng)該包括你模板中所有要訪問(wèn)的值。比如如果你返回 dict( newvalue = 5 ),那么模板中的 ${newvalue} 變量的值就會(huì)是 5。 某些時(shí)候,在處理某個(gè)請(qǐng)求時(shí)你可能會(huì)發(fā)現(xiàn),你需要一個(gè)不同的模板,而不是此前在 @expose 中指定的那個(gè)。你可以為返回的字典指定一個(gè) ‘tg_template‘ 鍵,然后以合適的模板名稱(chēng)作為它的值,例如:
dict( tg_template = ‘packagename.templates.lancelot‘ )
這樣 TurboGears 就會(huì)將返回值填充到上述指定的 lancelot 模板文件中,而不是 expose 中指定的那個(gè)模板。 9、返回 XML 而不是 HTML Kid 首先就是一個(gè) XML 模板語(yǔ)言。使用 HTML 轉(zhuǎn)換器,它可以產(chǎn)生優(yōu)良的 HTML 文件。同時(shí),如果使用其它的轉(zhuǎn)換器,你還可以用它生產(chǎn) XHTML 或其它 XML 格式的文檔。 expose 函數(shù)允許你指定格式(可是以“json”或 Kid 的某種轉(zhuǎn)換器)和內(nèi)容類(lèi)型。假設(shè)你想產(chǎn)生 RSS 文件,你可以把你的 expose 設(shè)置成這樣:
@expose( template = ‘project.templates.rss‘, format = ‘xml‘, content_type = ‘text/xml+rss‘ )
expose 函數(shù)的模式輸出格式是 HTML,但通過(guò)上述方式,你可以很容易的得到所需要的格式。
TurboGears(六)11、設(shè)計(jì)友好 因?yàn)閷?xiě)的模板是標(biāo)準(zhǔn)的 XHTML,所以我們可以直接用瀏覽器打開(kāi) Kid 模板文件。這很重要而且很有用,可以保證你的模板在瀏覽器中看起來(lái)美觀。 你可以從中觀查你的樣式表、JavaScript腳本、以及應(yīng)該出現(xiàn)動(dòng)態(tài)內(nèi)容的部分,是不是同你設(shè)想的一樣。 有時(shí)候,當(dāng)你直接瀏覽模板文件或執(zhí)行后的模板文件時(shí),它們可能不能正確的鏈接到它們的樣式表文件。要避免這個(gè),你可以使用 href 標(biāo)識(shí)要瀏覽的模板、使用 py:attrs 處理執(zhí)行后的頁(yè)面。例如:
<link rel=‘stylesheet‘ type=‘text/css‘ href=‘/path/to/file.css‘ py:attrs=‘href="/path/on/website"‘ />
這樣再在瀏覽器中查看模板的話,瀏覽器只會(huì)去查找 href 屬性,樣式表就會(huì)正確的被載入了。 12、共用頁(yè)眉和頁(yè)腳 Kid 提供了幾中方式來(lái)共用頁(yè)眉和頁(yè)腳,我們來(lái)集中看其中的一種。 Kid 有一個(gè)非常有用的命令 py:match,它可以用來(lái)創(chuàng)建一個(gè)匹配模式,然后在模板的其它位置引用它。 假設(shè)我們想將頁(yè)眉頁(yè)腳應(yīng)用于這樣一個(gè)模板:
<html xmlns:py="http:///kid/ns#" py:extends="‘master.kid‘"> <body> <h2>You‘re running TurboGears!</h2> </body> </html>
上述模板文件中,對(duì)獲得頁(yè)眉和頁(yè)腳來(lái)說(shuō)最重要的部分應(yīng)該是 html 標(biāo)簽中的 py:extends 了。py:extends 可以從其它多個(gè)模塊或模板文件中繼承它們定義的 py:def 和 py:match。對(duì)于上面這個(gè)例子來(lái)說(shuō),py:extends 會(huì)把 master.kid 模板文件中定義的 py:def、py:match 導(dǎo)入到當(dāng)前模板文件的名稱(chēng)空間中,然后這些定義就會(huì)直接在當(dāng)前模板文件中有效,就像這些定義就在當(dāng)前模板文件中一樣。 master.kid 看起來(lái)可能會(huì)是這樣:
<html xmlns:py="http:///kid/ns#"> <body py:match="item.tag==‘body‘"> <h1>會(huì)發(fā)生變化嗎?</h1> </body> </html>
為了敘述方便,我們假設(shè)第一個(gè)例子那個(gè)文件保存為 test.kid,而這個(gè)例子當(dāng)然是 master.kid。我們來(lái)看 master.kid 中 body 標(biāo)簽中的 py:match。它的意思是在文件中尋找接下來(lái)的 <body> 標(biāo)簽,如果找到的話,把它里面的內(nèi)容替換為當(dāng)前定義的內(nèi)容。 現(xiàn)在,我們?cè)?test.kid 繼承了這個(gè) py:match,那 test.kid 中的 body 部分會(huì)不會(huì)被 master.kid 中的 body 部分來(lái)代替呢?來(lái)驗(yàn)證一下:
xxx@x[~]$ kid test.kid <?xml version="1.0" encoding="utf-8"?> <html> <body> <h1>會(huì)發(fā)生變化嗎?</h1> </body>
結(jié)果很明顯,body 部分的內(nèi)容被替換掉了。 但是,如果我還想保留 test.kid 中的部分該怎么辦呢?可以對(duì) master.kid 稍作修改:
<html xmlns:py="http:///kid/ns#"> <body py:match="item.tag==‘body‘"> <h1>會(huì)發(fā)生變化嗎?</h1> <div py:replace=‘item[:]‘ /> </body> </html>
這時(shí),再來(lái)看一下結(jié)果:
xxx@x[~]$ kid test.kid <?xml version="1.0" encoding="utf-8"?> <html> <body> <h1>會(huì)發(fā)生變化嗎?</h1> <h2>You‘re running TurboGears!</h2> </body>
test.kid 中的內(nèi)容被保留了。利用這個(gè)原理,我們就可以在 master.kid 中寫(xiě)共用的頁(yè)眉和頁(yè)腳了。但是
<div py:replace=‘item[:]‘ />
是什么意思呢?我們?cè)賮?lái)做個(gè)測(cè)試好了,先對(duì) test.kid 稍加修改:
<html xmlns:py="http:///kid/ns#" py:extends="‘master.kid‘"> <body> <h2>You‘re running TurboGears!</h2> <h2>這次該顯示了吧!</h2> </body> </html>
master.kid 也做一丁點(diǎn)兒的變動(dòng),把 item[:] 改為 item[1:],再來(lái)看一下結(jié)果:
xxx@x[~]$ kid test.kid <?xml version="1.0" encoding="utf-8"?> <html> <body> <h1>會(huì)發(fā)生變化嗎?</h1> <h2>這次該顯示了吧!</h2> </body>
item[:] 是什么意思,也就不言自明了吧。 TurboGears(五)10、Kid 模板語(yǔ)言簡(jiǎn)介 Kid 模板可以是任何形式的 XML 文檔,只要在名稱(chēng)空間中告訴它如何處理這個(gè)模板就行了。在實(shí)際使用時(shí),則通常是 XHTML 文檔,經(jīng)過(guò)處理轉(zhuǎn)換為切實(shí)可用的 HTML 文檔。 這是摘自 Kid 官方文檔的一個(gè)例子,Kid 模板基本上就是這個(gè)樣子:
<?python
title = ‘A Kid Test Document‘
fruits = [ ‘a(chǎn)pple‘, ‘orange‘, ‘kiwi‘, ‘M&M‘ ]
from platform import system
?>
<html xmlns:py=‘http:///kid/ns#‘>
<head>
<title py:content=‘title‘>This is replaced.</title>
</head>
<body>
<p>These are some of my favorite fruits:</p>
<ul>
<li py:for=‘fruit in fruits‘>
I like ${fruit}s
</li>
</ul>
<p py:if=‘system() == ‘Linux‘>
Good for you!
</p>
</body>
</html>
使用 Kid 模板需要重點(diǎn)注意的是:
有關(guān) Kid 的最美妙事是,你所知道的一切 Python 的用法基本上都可以用到這里。舉個(gè)例子,py:for=‘fruit in fruits‘ 同 Python 中的 for fruit in fruits: 是一樣的意思。 在真正使用 TurboGears 開(kāi)發(fā)應(yīng)用程序時(shí),如下的代碼
<?python title = ‘A Kid Test Document‘ fruits = [ ‘a(chǎn)pple‘, ‘orange‘, ‘kiwi‘, ‘M&M‘ ] from platform import system ?>
并不會(huì)直接寫(xiě)在模板文件里,而是定義成一個(gè)字典。它其中的所有變量你都可以當(dāng)成模板中的變量來(lái)用。 變量傳入模板時(shí),Kid 會(huì)自動(dòng)對(duì)它們轉(zhuǎn)義。例如,你基本上不用考慮變量值如果包含 < 會(huì)不會(huì)出現(xiàn)錯(cuò)誤,Kid 會(huì)自動(dòng)將它轉(zhuǎn)換成 <。但如果你就是要傳入一段 XHTML 代碼,不想讓它們被自動(dòng)轉(zhuǎn)義,你可以使用 XML() 函數(shù)。舉個(gè)例子來(lái)說(shuō),假如有個(gè)變量 X,它的值為
<title>Title</title>
默認(rèn)情況下,Kid 會(huì)將它轉(zhuǎn)換為
<title>Title</title>
如果你希望轉(zhuǎn)換后的結(jié)果仍舊為 HTML 代碼的話,你需要這樣使用 X 變量:
${XML( X )}
我們來(lái)測(cè)試一下,假如 test.kid 內(nèi)容如下:
<?python
title = ‘‘
?>
<html xmlns:py="http:///kid/ns#">
<head>
${title}
</head>
<body>
${XML(title)}
</body>
</html>
當(dāng)然,真實(shí)的文件中不會(huì)這樣寫(xiě),我們這里只是為了測(cè)試?,F(xiàn)在打開(kāi)終端:
xxx@x[~]$ kid test.kid <?xml version="1.0" encoding="utf-8"?> <html> <head> <title>Title</title> </head> <body> <title>Title</title> </body>
結(jié)果跟我們上面所說(shuō)的一樣。關(guān)于 Kid 還有很多東西要學(xué),我隨后會(huì)單獨(dú)作 Kid 的學(xué)習(xí)筆記。你也可以查看 Kid 語(yǔ)言指南來(lái)了解更多的東西。
|
|
|
來(lái)自: 昵稱(chēng)11338 > 《TurboGears》