摘要:模板函數(shù)到底長(zhǎng)什么樣下面我們就可以來(lái)看看模板函數(shù)到底長(zhǎng)什么樣了。當(dāng)然,首先得創(chuàng)建一個(gè)模板文件??偨Y(jié)通過(guò)打印中間結(jié)果和分析代碼,我們已經(jīng)大概知道了的模板是如何轉(zhuǎn)化成內(nèi)容的。下一篇文章會(huì)闡述模板的各種語(yǔ)法所對(duì)應(yīng)的動(dòng)態(tài)函數(shù)內(nèi)容。
web.py模板的實(shí)現(xiàn)原理
web.py的模板實(shí)現(xiàn)利用了Python的可執(zhí)行對(duì)象的動(dòng)態(tài)特性:根據(jù)模板內(nèi)容和渲染函數(shù)的參數(shù)創(chuàng)建一個(gè)函數(shù),該函數(shù)執(zhí)行的時(shí)候會(huì)返回一個(gè)TemplateResult類(lèi)實(shí)例,該實(shí)例的字符串化就是模板對(duì)應(yīng)的HTML內(nèi)容。
實(shí)驗(yàn)環(huán)境搭建為了說(shuō)明web.py的模板是如何實(shí)現(xiàn)的,我們需要在web.py的模板實(shí)現(xiàn)代碼中加入一些打印語(yǔ)句來(lái)顯示中間結(jié)果。Python的virtualenv工具很好的實(shí)現(xiàn)了這個(gè)需求。另外,我還使用了iPython,不過(guò)Python標(biāo)準(zhǔn)命令行也是可以的。環(huán)境搭建的步驟簡(jiǎn)述如下:
創(chuàng)建virtualenv環(huán)境:virtualenv env
激活virtualenv環(huán)境:cd env以及source bin/activate
安裝web.py:pip install web.py
這個(gè)web.py庫(kù)會(huì)被安裝在virtualenv環(huán)境的目錄下:
(env)? ~/programming/python/env/lib/python2.7/site-packages/web $ pwd /home/diabloneo/programming/python/env/lib/python2.7/site-packages/web
下面就可以修改這個(gè)web.py的代碼來(lái)看看模板到底是如何實(shí)現(xiàn)的。
實(shí)驗(yàn)代碼修改我們要修改的代碼位于web/template.py文件內(nèi),找到Template類(lèi)的compile_template函數(shù)(在template.py文件的第900行),加入一行打印語(yǔ)句:
def compile_template(self, template_string, filename): code = Template.generate_code(template_string, filename, parser=self.create_parser()) def get_source_line(filename, lineno): try: lines = open(filename).read().splitlines() return lines[lineno] except: return None print code # 這行就是我們?cè)黾拥恼{(diào)試語(yǔ)句,可以打印出前面提到的動(dòng)態(tài)生成的函數(shù)。 try: # compile the code first to report the errors, if any, with the filename compiled_code = compile(code, filename, "exec") except SyntaxError, e: ...模板函數(shù)到底長(zhǎng)什么樣?
下面我們就可以來(lái)看看模板函數(shù)到底長(zhǎng)什么樣了。當(dāng)然,首先得創(chuàng)建一個(gè)模板文件。在我們的實(shí)驗(yàn)環(huán)境中進(jìn)行如下操作:
(env)? ~/programming/python/env $ ls bin include lib local (env)? ~/programming/python/env $ mkdir app (env)? ~/programming/python/env $ ls app bin include lib local (env)? ~/programming/python/env $ cd app (env)? ~/programming/python/env/app $ mkdir templates
現(xiàn)在,在templates目錄下創(chuàng)建一個(gè)最簡(jiǎn)單的模板,文件名為hello.html,內(nèi)容如下:
hello, world
下面來(lái)看看根據(jù)這個(gè)模板生成的函數(shù)到底長(zhǎng)什么樣子,在實(shí)驗(yàn)環(huán)境下啟動(dòng)ipython或者python,進(jìn)入到app目錄:
(env)? ~/programming/python/env/app $ ipython WARNING: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv. Python 2.7.8 (default, Oct 20 2014, 15:05:19) Type "copyright", "credits" or "license" for more information. IPython 1.0.0 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython"s features. %quickref -> Quick reference. help -> Python"s own help system. object? -> Details about "object", use "object??" for extra details. In [1]:
執(zhí)行如下代碼就可以看到模板函數(shù)的內(nèi)容:
In [3]: hello = web.template.frender("templates/hello.html") # coding: utf-8 def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u"hello, world "]) return self In [4]:
上面的函數(shù)__template__()就是我們?cè)黾拥絯eb.py庫(kù)中的那行print code所打印出來(lái)的。從這個(gè)函數(shù)的定義,我們可以看出:
函數(shù)內(nèi)使用了一些預(yù)定義的對(duì)象:ForLoop,TemplateResult等。
函數(shù)的結(jié)果是返回一個(gè)TemplateResult實(shí)例。
那么,現(xiàn)在問(wèn)題來(lái)了:
這個(gè)函數(shù)是如何生成的?
使用的這些預(yù)定義名稱(chēng)從哪里來(lái)的?
TemplateResult實(shí)例的字符串表示如何變成HTML文本的?
本文先來(lái)說(shuō)明TemplateResult實(shí)例是如何產(chǎn)生HTML文本這個(gè)問(wèn)題。
TemplateResultTemplateResult類(lèi)的定義也在web/template.py文件中,繼承的類(lèi)和實(shí)現(xiàn)的方法如下:
class TemplateResult(object, DictMixin): __delattr__ : function __delitem__ : function __getattr__ : function __getitem__ : function __init__ : function __repr__ : function __setattr__ : function __setitem__ : function __str__ : function __unicode__ : function _prepare_body : function keys : function
其中DictMixin是一個(gè)實(shí)現(xiàn)了大部分字典操作的類(lèi),繼承該類(lèi)的子類(lèi)(也就是這里的TemplateResult)需要實(shí)現(xiàn):__getitem__(), __setitem__(), __delitem__()和keys()方法,以便對(duì)象可以模擬完整的字典操作。需要說(shuō)明的是:DictMixin類(lèi)已經(jīng)過(guò)時(shí)了,現(xiàn)在應(yīng)該使用collections.MutableMapping類(lèi)(該類(lèi)的實(shí)現(xiàn)利用了abc庫(kù)--抽象類(lèi))。
先來(lái)看__init__()函數(shù),
def __init__(self, *a, **kw): self.__dict__["_d"] = dict(*a, **kw) self._d.setdefault("__body__", u"") self.__dict__["_parts"] = [] self.__dict__["extend"] = self._parts.extend
從初始化函數(shù)可以看出,TemplateResult大部分屬性都存儲(chǔ)在_d這個(gè)字典中,該字典至少包含一個(gè)元素body。所以,外部代碼對(duì)TemplateResult的對(duì)象屬性進(jìn)行增刪改查操作時(shí),實(shí)際上都是在操作內(nèi)部的_d這個(gè)字典。初始化函數(shù)中定義的另外兩個(gè)屬性是:_parts,一個(gè)序列;extend,指向_parts序列的extend()方法,也就是說(shuō)調(diào)用TemplateResult實(shí)例的extend方法實(shí)際上是調(diào)用實(shí)例屬性_parts的extend方法。這個(gè)extend方法我們?cè)谇懊娴?strong>__template__()函數(shù)已經(jīng)見(jiàn)到過(guò)了:
def __template__(): __lineoffset__ = -5 loop = ForLoop() self = TemplateResult(); extend_ = self.extend extend_([u"hello, world "]) return self
這個(gè)函數(shù)定義了extend_ = self.extend,extend_把模板的內(nèi)容添加到了self._parts這個(gè)序列中。
下面來(lái)看一下TemplateResult如何生成HTML內(nèi)容,這個(gè)就要看__str__()方法了:
def _prepare_body(self): """Prepare value of __body__ by joining parts. """ if self._parts: value = u"".join(self._parts) self._parts[:] = [] body = self._d.get("__body__") if body: self._d["__body__"] = body + value else: self._d["__body__"] = value def __str__(self): self._prepare_body() return self["__body__"].encode("utf-8")
主要操作是在_prepare_body()函數(shù)里,主要操作是把_parts中的字符串拼接起來(lái),然后再拼接到body的內(nèi)容后面。
看過(guò)TemplateResult的實(shí)現(xiàn)后,我們可以知道,由模板生成的__template__()函數(shù)最終會(huì)把一堆字符串添加到TemplateResult實(shí)例中,然后再通過(guò)實(shí)例生成HTML字符串。
總結(jié)通過(guò)打印中間結(jié)果和分析代碼,我們已經(jīng)大概知道了web.py的模板是如何轉(zhuǎn)化成HTML內(nèi)容的。下一篇文章會(huì)闡述web.py模板的各種語(yǔ)法所對(duì)應(yīng)的動(dòng)態(tài)函數(shù)內(nèi)容。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/45359.html
摘要:上一篇文章源碼分析模板說(shuō)明了的模板的大致工作原理。本文重點(diǎn)講述模板支持的語(yǔ)法是如何轉(zhuǎn)換生成函數(shù)的。模板的名稱(chēng)統(tǒng)一是。模板代碼斷行模板內(nèi)容函數(shù)內(nèi)容從結(jié)果來(lái)看,模板中的斷行只是為了不再結(jié)果中插入一個(gè)多余的換行符而已。 上一篇文章web.py源碼分析: 模板(1)說(shuō)明了web.py的模板的大致工作原理。本文重點(diǎn)講述web.py模板支持的語(yǔ)法是如何轉(zhuǎn)換生成__template__函數(shù)的。 we...
摘要:前兩篇文章主要說(shuō)明了的模板系統(tǒng)將模板文件處理后得到的結(jié)果函數(shù)。生成函數(shù)的代碼這個(gè)是模板生成過(guò)程中最長(zhǎng)最復(fù)雜的一段,會(huì)應(yīng)用到的分析功能以及動(dòng)態(tài)編譯功能。參數(shù)都是一個(gè),表示還未解析的模板內(nèi)容。 前兩篇文章主要說(shuō)明了web.py的模板系統(tǒng)將模板文件處理后得到的結(jié)果:__template__()函數(shù)。本文主要講述模板文件是如何變成__template__()函數(shù)的。 Render和frende...
摘要:前言在文章基于環(huán)境搭建框架方法介紹中介紹了客戶(hù)端和服務(wù)器的交互過(guò)程,服務(wù)器接收客戶(hù)端的請(qǐng)求后,由應(yīng)用服務(wù)器對(duì)瀏覽器的請(qǐng)求進(jìn)行處理,將生成的響應(yīng)傳遞給服務(wù)器,再由服務(wù)器返回給客戶(hù)端。 前言 在文章《基于Linux環(huán)境搭建Nginx+uWSGI+Python框架方法介紹》中介紹了客戶(hù)端和Web服務(wù)器的交互過(guò)程,Web服務(wù)器接收客戶(hù)端的請(qǐng)求后,由Web應(yīng)用服務(wù)器對(duì)瀏覽器的請(qǐng)求進(jìn)行處理,將生成...
摘要:是應(yīng)用性能管理監(jiān)控解決方案提供商。目錄是列出的命令腳本所在目錄。包含文件如下的函數(shù)是命令執(zhí)行的入口。而對(duì)于硬件信息的檢測(cè)則由進(jìn)行。文檔地址源碼仔細(xì)看下去,太復(fù)雜了。下一篇再分析一個(gè)請(qǐng)求到結(jié)束探針工作的完整過(guò)程吧。 Newrelic 是APM(Application Performance Management)(應(yīng)用性能管理/監(jiān)控)解決方案提供商。項(xiàng)目中,通常用它來(lái)追蹤應(yīng)用的性能。最近...
摘要:本文主要分析的是庫(kù)的這個(gè)模塊中的代碼。將結(jié)果轉(zhuǎn)換成一個(gè)迭代器。函數(shù)函數(shù)的定義如下位置位置位置該函數(shù)的參數(shù)中就是,是路由映射表則是,是本次請(qǐng)求路徑。位置,如果是其他情況,比如直接指定一個(gè)類(lèi)對(duì)象作為處理對(duì)象。 本文主要分析的是web.py庫(kù)的application.py這個(gè)模塊中的代碼。總的來(lái)說(shuō),這個(gè)模塊主要實(shí)現(xiàn)了WSGI兼容的接口,以便應(yīng)用程序能夠被WSGI應(yīng)用服務(wù)器調(diào)用。WSGI是We...
閱讀 2231·2021-11-22 14:56
閱讀 9834·2021-09-08 10:45
閱讀 1966·2019-08-30 13:54
閱讀 2857·2019-08-29 16:54
閱讀 2003·2019-08-29 14:20
閱讀 1772·2019-08-29 12:25
閱讀 1851·2019-08-29 12:17
閱讀 1048·2019-08-23 18:29