在 Python 中寫 HTML 不是聰明的選擇,相反在 HTML 中寫 Python 則有趣的多兽狭。幸運的是憾股,web.py 讓這件事情做得簡單而又漂亮。
創(chuàng)建模板
這里箕慧,我們先在項目中新建一個目錄templates
集中存放模板文件服球,便于管理。然后在templates下新建一個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>
這是一個最簡單的html頁面代碼斩熊。
使用模板
然后在修改使用這個模板的類,比如說我們在main.py模塊中的新寫一個index
類伐庭,入下:
class index:
def GET(self):
render=web.template.render(“templates”)
return render.index(“Lisa”)
同時修改urls為:
urls = (“/”, “index”)
這樣粉渠,網(wǎng)站默認調(diào)用index類,進而使用index.html模板圾另,打開瀏覽器查看結(jié)果霸株,頁面就會打印出 Hello, Lisa
的字樣。
除此之外還有兩種使用模板的方法:
-
使用frender直接指定模板文件集乔,GET函數(shù)最后兩行改為:
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)
表示本模板接受一個名為name的參數(shù),也就是對應(yīng)index類中return render.index(“Lisa”)
中的Lisa扰路。而render=web.template.render(“templates”)
表示創(chuàng)建一個模板對象尤溜,模板是存放于templates目錄下,然后就可以用所創(chuàng)建的 render 對象來訪問相應(yīng)的模板
比如templates目錄下的index.html就是用render.index來表示(實際上是匹配尋找index.*文件汗唱,第一個匹配的就認為是所對應(yīng)的模板文件
)宫莱,如果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返回的時候賦予對應(yīng)兩個參數(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ū)別室埋。
對象賦值
向?qū)ο筚x值時需要在$
與對象名
之間留空格,如為一個名為vara的字符串對象賦值apple的代碼為$ vara = “apple”
伊约。
另外姚淆,對象賦值語句必須獨占一行,前面或后面有其他代碼則會程序出錯屡律。
對象引用
引用對象的時候直接使用 $+對象名
的形式腌逢,如$vara
。
另外引用對象時還可以用{}
或()
將對象進行明確的分組疹尾,如$(vara)s就會表示apples
上忍,如果沒有括號骤肛,程序則會把 $varas
作為一個整體纳本,也就變成對varas對象的引用而發(fā)生錯誤。
另如果向如下定義兩個數(shù)字型對象:
$varb = 1
$varc = 2
然后希望計算兩個值的和腋颠,如果用$varb+$varc
的形式繁成,頁面上只會得到1+2而不是3,這時也就需要把兩個對象放在括號里淑玫,如$(varb+varc)
的形式才能得到正確答案3巾腕。
注釋
模板中支持單行注釋
面睛,以$#
符號開始到行末都是注釋內(nèi)容。
$#This is comment
注釋前面可以有其他內(nèi)容尊搬,但是不可以有賦值代碼叁鉴。
如下代碼是正確的:
Hi $#This is comment
但下面的則會出錯:
$ vara = “apple” $#This is comment
打印$符號
由于$
符號在模板中有特殊用途,所以在頁面上輸出$
時需要進行轉(zhuǎn)義操作佛寿,用連續(xù)兩個$
表示在頁面上輸出一個$符號幌墓。
Can you lend me $$50?
控制代碼(循環(huán)、條件判斷)
模板中支持for冀泻、while常侣、if、elif弹渔、else
胳施,用法與在python一致,只是控制代碼行要以$開始(包括break和continue命令)肢专,$開始的代碼行中對象不需要在前面再加$符號舞肆,同時要注意縮進規(guī)則,如:
for 循環(huán):
$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循環(huán)中鸟召,有一組內(nèi)置的變量可以使用胆绊,非常方便,分別如下所示:
- 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,odd
2,1,False,False,False,True,even
3,2,False,False,True,False,odd
4,3,False,True,False,True,even
函數(shù)-$def
函數(shù)定義也是與在python中類似压状,用def,只是也要在前面加$
跟继,代碼也要注意$
的使用和縮進:
$def hello(name=”"):
Hello $name!
函數(shù)調(diào)用也是用$
加函數(shù)名的形式:
$hello(“Lisa”)
當然种冬,定義函數(shù)時也可以與html代碼混編:
$def hello(name=”"):
<strong/>Hello $name!</strong>
但是調(diào)用的時候需要在函數(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
那么結(jié)果顯示在頁面上的就是this is vara
這句話。
要注意一點的是夕凝,這種變量是字符串宝穗,即便如下定義變量:
$var vara: 0
Vara也并不是數(shù)字0户秤,
如果把GET函數(shù)最后改成:
return render.index(“Lisa”, “Hayes”).vara+1
會導致程序出錯。如果希望得到期望中的結(jié)果1逮矛,則需要如下形式代碼:
return int(render.index(“Lisa”, “Hayes”).vara)+1
builtins and globals
在模板中鸡号,用戶可以直接使用python的內(nèi)建函數(shù)和變量,寫函數(shù)變量包括range, min, max 以及 True 和 False等须鼎。 除此之外膜蠢,如果希望在模板中使用其他的非內(nèi)建功能,就需要一點特殊操作莉兰。要在創(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={})
模板復用
當多個頁面有著相同的結(jié)構(gòu)框架的時候,為每一個頁面單獨維護一個模板就顯得比較麻煩捶朵,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合并在一起的結(jié)果羡鸥,index.html中的內(nèi)容被嵌入到layout.html中的$:content處。
在layout.html模板中還可以引用index.html中定義的var變量忠寻,這為程序帶來了更多的靈活性
惧浴,比如我們希望在不同的頁面在使用同一個layout模板的時候能有不同的title,可以在使用layout的模板中定義如下一個var變量:
$var title:This is index.html
然后在layout.html中的title處修改為:
<title>$content.title</title>
這樣奕剃,訪問index.html時顯示在瀏覽器上的title就是This is index.html衷旅,而不是原來的Layout了。
在模板中使用python代碼模塊
在默認狀態(tài)下纵朋,在模板中是不能直接調(diào)用其他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部分就是這個要在模塊中使用的模塊或?qū)ο蟮恼鎸嵜Q了。
最后在要使用此模塊的模板中就可以用$m1來引用此模塊了胆建。比如在index.html中添加下面一行代碼:
$m1.hello_from_m1(gname)
就會調(diào)用module1中的hello_from_m1函數(shù)烤低,在頁面上打印出:
hello Lisa, this is module1
在web.py模板中使用jQuery
在jQuery中$
也是一個關(guān)鍵字,這樣的話如果在模板中使用jQuery就會沖突笆载,這時候只需要用$$
做一下轉(zhuǎn)義就可以了扑馁,比如:
<script type=”text/javascript”>
$$(document).ready(function()
{
alert(“It works.”);
});
</script>