這節(jié)以及后面的習(xí)題中,你的任務(wù)是把前面創(chuàng)建的游戲做成網(wǎng)頁(yè)版。這是本書的最后三個(gè)章節(jié),這些內(nèi)容對(duì)你來說難度會(huì)相當(dāng)大,你要在上面花些時(shí)間才能做出來。在你開始這節(jié)練習(xí)以前,你必須已經(jīng)成功地完成過了《習(xí)題 46》的內(nèi)容,正確安裝了 pip,而且學(xué)會(huì)了如何安裝軟件包以及如何創(chuàng)建項(xiàng)目骨架。如果你不記得這些內(nèi)容,就回到《習(xí)題 46》重新復(fù)習(xí)一遍。
在創(chuàng)建你的第一個(gè)網(wǎng)頁(yè)應(yīng)用程序之前,你需要安裝一個(gè)“Web 框架”,它的名字叫 lpthw.web。所謂的“框架”通常是指“讓某件事情做起來更容易的軟件包”。在網(wǎng)頁(yè)應(yīng)用的世界里,人們創(chuàng)建了各種各樣的“網(wǎng)頁(yè)框架”,用來解決他們?cè)趧?chuàng)建網(wǎng)站時(shí)碰到的問題,然后把這些解決方案用軟件包的方式發(fā)布出來,這樣你就可以利用它們引導(dǎo)創(chuàng)建你自己的項(xiàng)目了。
可選的框架類型有很多很多,不過在這里我們將使用 lpthw.web 框架。你可以先學(xué)會(huì)它,等到差不多的時(shí)候再去接觸其它的框架,不過 lpthw.web 本身挺不錯(cuò)的,所以就算你一直使用也沒關(guān)系。
使用 pip 安裝 lpthw.web:
$ sudo pip install lpthw.web
[sudo] password for zedshaw:
Downloading/unpacking lpthw.web
Running setup.py egg_info for package lpthw.web
Installing collected packages: lpthw.web
Running setup.py install for lpthw.web
Successfully installed lpthw.web
Cleaning up...
以上是 Linux 和 Mac OSX 系統(tǒng)下的安裝命令,如果你使用的是 Windows,那你只要把 sudo 去掉就可以了。如果你無法正常安裝,請(qǐng)回到《習(xí)題 46》,確認(rèn)自己學(xué)會(huì)了里邊的內(nèi)容。
Warning
其他 Python 程序員會(huì)警告你說 lpthw.web 只是另外一個(gè)叫做 web.py 的 Web 框架的代碼分支(fork),而 web.py 又包含了太多的“魔法(magic)”在里邊。如果他們這么說的話,你告訴他們 Google App Engine 最早用的就是 web.py,但沒有一個(gè) Python 程序員抱怨過它里邊包含了太多的魔法,因?yàn)?Google 用它也沒啥問題。如果 Google 覺得它可以,那它對(duì)你來說也不會(huì)差。所以還是回去繼續(xù)學(xué)習(xí)吧,他們這些說法與其說是教導(dǎo)你,不如說是拿他們自己的教條束縛你,你還是忽略這些說法好了。
現(xiàn)在你將做一個(gè)非常簡(jiǎn)單的“Hello World”項(xiàng)目出來,首先你要?jiǎng)?chuàng)建一個(gè)項(xiàng)目目錄:
$ cd projects
$ mkdir gothonweb
$ cd gothonweb
$ mkdir bin gothonweb tests docs templates
$ touch gothonweb/__init__.py
$ touch tests/__init__.py
你最終的目的是把《習(xí)題 42》中的游戲做成一個(gè) web 應(yīng)用,所以你的項(xiàng)目名稱叫做 gothonweb,不過在此之前,你需要?jiǎng)?chuàng)建一個(gè)最基本的 lpthw.web 應(yīng)用,將下面的代碼放到 bin/app.py 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import web
urls = (
'/', 'index'
)
app = web.application(urls, globals())
class index:
def GET(self):
greeting = "Hello World"
return greeting
if __name__ == "__main__":
app.run()
|
然后使用下面的方法來運(yùn)行這個(gè) web 程序:
$ python bin/app.py
http://0.0.0.0:8080/
不過如果你執(zhí)行下面的命令:
$ cd bin/ # WRONG! WRONG! WRONG!
$ python app.py # WRONG! WRONG! WRONG!
那你就錯(cuò)了。在所有的 python 項(xiàng)目中,你都不需要進(jìn)到底層目錄去運(yùn)行東西。你應(yīng)該停留在最上層目錄運(yùn)行,這樣才能保證所有的模組和文件能被正常訪問到。如果你犯了這個(gè)錯(cuò)誤,就請(qǐng)回到《習(xí)題 46》學(xué)習(xí)一下關(guān)于項(xiàng)目布局的知識(shí)。
最后,使用你的網(wǎng)頁(yè)瀏覽器,打開 URL http://localhost:8080/,你應(yīng)該看到兩樣?xùn)|西,首先是瀏覽器里顯示了 Hello, world!,然后是你的命令行終端顯示了如下的輸出:
$ python bin/app.py
http://0.0.0.0:8080/
127.0.0.1:59542 - - [13/Jun/2011 11:44:43] "HTTP/1.1 GET /" - 200 OK
127.0.0.1:59542 - - [13/Jun/2011 11:44:43] "HTTP/1.1 GET /favicon.ico" - 404 Not Found
這些是 lpthw.web 打印出的 log 信息,從這些信息你可以看出服務(wù)器有在運(yùn)行,而且能了解到程序在瀏覽器背后做了些什么事情。這些信息還有助于你發(fā)現(xiàn)程序的問題。例如在最后一行它告訴你瀏覽器試圖獲取 /favicon.ico,但是這個(gè)文件并不存在,因此它返回的狀態(tài)碼是 404 Not Found。
到這里,我還沒有講到任何 web 相關(guān)的工作原理,因?yàn)槭紫饶阈枰瓿蓽?zhǔn)備工作,以便后面的學(xué)習(xí)能順利進(jìn)行,接下來的兩節(jié)習(xí)題中會(huì)有詳細(xì)的解釋。我會(huì)要求你用各種方法把你的 lpthw.web 應(yīng)用程序弄壞,然后再將其重新構(gòu)建起來:這樣做的目的是讓你明白運(yùn)行lpthw.web 程序需要準(zhǔn)備好哪些東西。
在瀏覽器訪問到你的網(wǎng)頁(yè)應(yīng)用程序時(shí),發(fā)生了下面一些事情:
確定你真的弄懂了這些,你需要畫一個(gè)示意圖,來理清信息是如何從瀏覽器傳遞到 lpthw.web,再到 index.GET,再回到你的瀏覽器的。
第一步,把第 11 行的 greeting 變量賦值刪掉,然后刷新瀏覽器。你應(yīng)該會(huì)看到一個(gè)錯(cuò)誤頁(yè)面,你可以通過這一頁(yè)豐富的錯(cuò)誤信息看出你的程序崩潰的原因是什么。當(dāng)然你已經(jīng)知道出錯(cuò)的原因是 greeting 的賦值丟失了,不過 lpthw.web 還是會(huì)給你一個(gè)挺好的錯(cuò)誤頁(yè)面,讓你能找到出錯(cuò)的具體位置。試試在這個(gè)錯(cuò)誤頁(yè)面上做以下操作:
你已經(jīng)試過用各種方法把這個(gè) lpthw.web 程序改錯(cuò),不過你有沒有注意到“Hello World”不是一個(gè)好 HTML 網(wǎng)頁(yè)呢?這是一個(gè) web 應(yīng)用,所以需要一個(gè)合適的 HTML 響應(yīng)頁(yè)面才對(duì)。為了達(dá)到這個(gè)目的,下一步你要做的是將“Hello World”以較大的綠色字體顯示出來。
第一步是創(chuàng)建一個(gè) templates/index.html 文件,內(nèi)容如下:
$def with (greeting)
<html>
<head>
<title>Gothons Of Planet Percal #25</title>
</head>
<body>
$if greeting:
I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>.
$else:
<em>Hello</em>, world!
</body>
</html>
如果你學(xué)過 HTML 的話,這些內(nèi)容你看上去應(yīng)該很熟悉。如果你沒學(xué)過 HTML,那你應(yīng)該去研究一下,試著用 HTML 寫幾個(gè)網(wǎng)頁(yè),從而知道它的工作原理。不過我們這里的 HTML 文件其實(shí)是一個(gè)“模板(template)”,如果你向模板提供一些參數(shù),lpthw.web 就會(huì)在模板中找到對(duì)應(yīng)的位置,將參數(shù)的內(nèi)容填充到模板中。例如每一個(gè)出現(xiàn) $greeting 的位置,$greeting 的內(nèi)容都會(huì)被替換成對(duì)應(yīng)這個(gè)變量名的參數(shù)。
為了讓你的 bin/app.py 處理模板,你需要寫一寫代碼,告訴 lpthw.web 到哪里去找到模板進(jìn)行加載,以及如何渲染(render)這個(gè)模板,按下面的方式修改你的 app.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import web
urls = (
'/', 'Index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class Index(object):
def GET(self):
greeting = "Hello World"
return render.index(greeting = greeting)
if __name__ == "__main__":
app.run()
|
特別注意一下 render 這個(gè)新變量名,注意我修改了 index.GET 的最后一行,讓它返回了 render.index() ,并且將 greeting 變量作為參數(shù)傳遞給了這個(gè)函數(shù)。
改好上面的代碼后,刷新一下瀏覽器中的網(wǎng)頁(yè),你應(yīng)該會(huì)看到一條和之前不同的綠色信息輸出。你還可以在瀏覽器中通過“查看源文件(View Source)”看到模板被渲染成了標(biāo)準(zhǔn)有效的 HTML 源代碼。
這么講也許有些太快了,我來詳細(xì)解釋一下模板的工作原理吧:
要深入理解這個(gè)過程,你可以修改 greeting 變量以及 HTML 模板的內(nèi)容,看看會(huì)有什么效果。然后創(chuàng)建一個(gè)叫做 templates/foo.html 的模板,并且使用一個(gè)新的 render.foo 去渲染它。從這個(gè)過程你也可以看出,render 調(diào)用的函數(shù)名稱只要跟 templates/ 下的 .html 文件名匹配到,這個(gè) HTML 模板就可以被渲染到了。