摘要:上一篇文章源碼分析模板說明了的模板的大致工作原理。本文重點講述模板支持的語法是如何轉換生成函數的。模板的名稱統一是。模板代碼斷行模板內容函數內容從結果來看,模板中的斷行只是為了不再結果中插入一個多余的換行符而已。
上一篇文章web.py源碼分析: 模板(1)說明了web.py的模板的大致工作原理。本文重點講述web.py模板支持的語法是如何轉換生成__template__函數的。
web.py模板語法和__template__()函數的對應關系本章會列出模板內容以及轉換之后的__template__()函數的內容,以及必要的文字說明。模板的名稱統一是hello.html。
純字符串模板內容
hello, world
函數內容
def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u"hello, world "]) return selfdef with
模板內容
$def with (name, value=[], *args, **kargs) hello, $name
函數內容
def __template__ (name, value=[], *args, **kargs): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u"hello, ", escape_(name, True), u" "]) return self
從生成的函數可以看出,def with語法所生成的就是__template__()函數的參數列表。
表達式替換模板內容
$def with (name, value) $name ${name + value} $(name + value)ing. $name[value].function()
函數內容
def __template__ (name, value): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([escape_(name, True), u" "]) extend_([escape_((name + value), True), u" "]) extend_([escape_((name + value), True), u"ing. "]) extend_([escape_(name[value].function(), True), u" "]) return self
表達式的替換就是執行表達式(表達式對應的代碼),得到的結果添加到TemplateResult實例中。
賦值模板內容
$def with (name, func) $ name1 = name $ name2 = func()
函數內容
def __template__ (name, func): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend name1 = name name2 = func() return self
其實,轉換后就是Python代碼里的賦值語句。
內容過濾模板內容
$def with (name) $name $:name
函數內容
def __template__ (name): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([escape_(name, True), u" "]) extend_([escape_(name, False), u" "]) return self
從生成的代碼來看,是否使用過濾語法的區別就是傳入excape_函數的第二個參數,這個函數其實只是一個字符串處理函數,后續再說。
模板代碼斷行(newline suppression)模板內容
$def with (name, func) $name hello, $name ! $func(1, 2, 3, 4, 5)
函數內容
def __template__ (name, func): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([escape_(name, True), u" "]) extend_([u"hello, "]) extend_([escape_(name, True), u" "]) extend_([u"! "]) extend_([escape_(func(1, 2, 3, 4, 5), True), u" "]) return self
從結果來看,模板中的斷行只是為了不再結果中插入一個多余的換行符而已。另外,一個表達式的中間是不支持斷行的,就比如在模板中不能把func函數的參數列表寫成兩行。
$符號模板內容
$$
函數內容
def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u"$", u" "]) return self注釋
模板內容
$# comment line hello, world.
函數內容
def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u" "]) extend_([u"hello, world. "]) return self
模板中注釋的行在生成的函數中只有一個換行符。
控制結構 for循環模板內容
$for i in range(10): I like $i
函數內容
def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend for i in loop.setup(range(10)): extend_([u"I like ", escape_(i, True), u" "]) return self
模板中的for循環被轉換成了代碼中的for循環,而且用上了變量loop(ForLoop對象后續再來看)。
while循環模板內容
$def with (name_list) $while name_list: hello, $name_list.pop()
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u" "]) while name_list: extend_([u"hello, ", escape_(name_list.pop(), True), u" "]) return self
注意和for循環的區別,沒有使用loop變量。
for循環的loop變量模板內容
$def with (name_list) $for name in name_list: $loop.index $loop.index0 $loop.first $loop.last $loop.odd $loop.even $loop.parity $loop.parent hello, $name $for i in range(10): $for name in name_list: $loop.parent hello, $name
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend for name in loop.setup(name_list): extend_([escape_(loop.index, True), u" "]) extend_([escape_(loop.index0, True), u" "]) extend_([escape_(loop.first, True), u" "]) extend_([escape_(loop.last, True), u" "]) extend_([escape_(loop.odd, True), u" "]) extend_([escape_(loop.even, True), u" "]) extend_([escape_(loop.parity, True), u" "]) extend_([escape_(loop.parent, True), u" "]) extend_([u"hello, ", escape_(name, True), u" "]) extend_([u" "]) for i in loop.setup(range(10)): for name in loop.setup(name_list): extend_([escape_(loop.parent, True), u" "]) extend_([u"hello, ", escape_(name, True), u" "]) return self
這里展示了loop變量的成員,以及嵌套循環的使用。
if-else模板內容
$def with (name_list) $if name_list: $len(name_list) $else: 0
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend if name_list: extend_([escape_(len(name_list), True), u" "]) else: extend_([u"0 "]) return self
elif語句也支持。
函數定義模板內容
$def with (name_list) $def hello(name): hello, $name $def hello_to_all(nlist): $for each in nlist: $hello(each) $hello_to_all(name_list)
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u" "]) __lineoffset__ -= 3 def hello(name): self = TemplateResult(); extend_ = self.extend extend_([u"hello, ", escape_(name, True), u" "]) extend_([u" "]) return self __lineoffset__ -= 3 def hello_to_all(nlist): self = TemplateResult(); extend_ = self.extend for each in loop.setup(nlist): extend_([escape_(hello(each), True), u" "]) extend_([u" "]) return self extend_([escape_(hello_to_all(name_list), True), u" "]) return self
模板對函數的支持其實就是定義內部函數并且調用,每個內部函數的返回結果也都是TemplateResult實例。
code模板內容
$def with (name_list) $code: new_list = [x.upper() for x in name_list] def hello(name): return "hello, %s" % (name) more_new_list = [] for each in new_list: more_new_list.append(hello(each)) $hello("everybody") $len(more_new_list)
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u" "]) new_list = [x.upper() for x in name_list] def hello(name): return "hello, %s" % (name) more_new_list = [] for each in new_list: more_new_list.append(hello(each)) extend_([escape_(hello("everybody"), True), u" "]) extend_([escape_(len(more_new_list), True), u" "]) return self
code的語法有點復雜,其內部是用來定義原始的Python代碼的,有如下幾個特點:
code內部定義的函數也是內部函數,在模板的其他地方可以調用,但是不會把結果存放在TemplateResult實例中返回。
code中定義的變量都會作為__template__()函數的局部變量,在模板的其他地方可以調用。
注意,code塊中不要使用print語句打印輸出(雖然默認已經禁止了)。
var模板內容
$def with (name_list) $var title: hi $var title2: "hi" $var name: $name_list[0] $var name2: name_list[0]
函數內容
def __template__ (name_list): __lineoffset__ = -4 loop = ForLoop() self = TemplateResult(); extend_ = self.extend self["title"] = join_(u"hi") self["title2"] = join_(u""hi"") self["name"] = join_(escape_(name_list[0], True)) self["name2"] = join_(u"name_list[0]") return self
var是用來為模板設置屬性的,從生成的代碼來看,就是為TemplateResult實例設置屬性。上面的模板內容里有一些關鍵細節:
var name: value中的冒號后面的內容默認是作為字符串處理的,可以不用加引號,如果加了引號,則引號也會作為內容的一部分。
如果要在冒號后面訪問一些變量值,需要使用$前綴。
總結寫了這些web.py模板支持的語法和生成的代碼的對應關系,希望有助于大家理解模板的語法,了解每種語法的用途,避免踩坑。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45358.html
摘要:模板函數到底長什么樣下面我們就可以來看看模板函數到底長什么樣了。當然,首先得創建一個模板文件。總結通過打印中間結果和分析代碼,我們已經大概知道了的模板是如何轉化成內容的。下一篇文章會闡述模板的各種語法所對應的動態函數內容。 web.py模板的實現原理 web.py的模板實現利用了Python的可執行對象的動態特性:根據模板內容和渲染函數的參數創建一個函數,該函數執行的時候會返回一個Te...
摘要:前兩篇文章主要說明了的模板系統將模板文件處理后得到的結果函數。生成函數的代碼這個是模板生成過程中最長最復雜的一段,會應用到的分析功能以及動態編譯功能。參數都是一個,表示還未解析的模板內容。 前兩篇文章主要說明了web.py的模板系統將模板文件處理后得到的結果:__template__()函數。本文主要講述模板文件是如何變成__template__()函數的。 Render和frende...
摘要:本文主要分析的是庫的這個模塊中的代碼。將結果轉換成一個迭代器。函數函數的定義如下位置位置位置該函數的參數中就是,是路由映射表則是,是本次請求路徑。位置,如果是其他情況,比如直接指定一個類對象作為處理對象。 本文主要分析的是web.py庫的application.py這個模塊中的代碼。總的來說,這個模塊主要實現了WSGI兼容的接口,以便應用程序能夠被WSGI應用服務器調用。WSGI是We...
摘要:前言在文章基于環境搭建框架方法介紹中介紹了客戶端和服務器的交互過程,服務器接收客戶端的請求后,由應用服務器對瀏覽器的請求進行處理,將生成的響應傳遞給服務器,再由服務器返回給客戶端。 前言 在文章《基于Linux環境搭建Nginx+uWSGI+Python框架方法介紹》中介紹了客戶端和Web服務器的交互過程,Web服務器接收客戶端的請求后,由Web應用服務器對瀏覽器的請求進行處理,將生成...
摘要:是應用性能管理監控解決方案提供商。目錄是列出的命令腳本所在目錄。包含文件如下的函數是命令執行的入口。而對于硬件信息的檢測則由進行。文檔地址源碼仔細看下去,太復雜了。下一篇再分析一個請求到結束探針工作的完整過程吧。 Newrelic 是APM(Application Performance Management)(應用性能管理/監控)解決方案提供商。項目中,通常用它來追蹤應用的性能。最近...
閱讀 2577·2021-11-22 13:53
閱讀 4085·2021-09-28 09:47
閱讀 870·2021-09-22 15:33
閱讀 820·2020-12-03 17:17
閱讀 3321·2019-08-30 13:13
閱讀 2126·2019-08-29 16:09
閱讀 1183·2019-08-29 12:24
閱讀 2455·2019-08-28 18:14