學習tornado:模板

第一次接觸tornado的template,是在做oastub的時候,因爲一位同學在handler裏面硬編碼了html代碼,我決定引入template機制來降低邏輯與頁面的耦合。

簡介

tornado自帶了一個簡易的template引擎,使用它,我們可以很方便的構建自己的web頁面。tornado的template使用起來很簡單,如下:

from tornado.template import Template

t = Template("<html>{{ myvalue }}</html>")
t.generate(myvalue="Hello World")

#output: <html>Hello World</html>

可以看到,tornado的template很容易理解,我們加載一段模板代碼,tornado會將該代碼編譯成python code。具體的過程如下:

  • 解析template,生成code string
  • 使用compile編譯成code object
  • 使用exec執行該code object

expression

上面的例子,我們可以看到,在template裏面myvalue的值是在generate的時候傳入並生成的。tornado通過{{ }}將python的值插入模板裏面。也就是說,我們可以在雙括號裏面寫上任何python表達式,tornado在模板生成的時候會計算表達式的值,並插入輸出代碼裏面。如下:

Template("{{ 1 + 1 }}").generate()
# output: 2
Template("{{ Hello World }}").generate()
# output: hello world
Template("{{ [ i for i in range(10) ] }}").generate()
# output: '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'

control flow

不光支持表達式,tornado的template還可以通過{{% %}}來支持流程控制。tornado template支持的control有if,for,while和try,如下:

Template("{{% if a is 1 %}} Hello World {{% end %}}").generate(a = 1)
# output: ' Hello World '
Template("{{% if a is 1 %}} Hello World {{% end %}}").generate(a = 2)
# output: ' '

Template("{{% for name in names %}} {{ name }} {{% end %}}").generate(names = ['a', 'b', 'c'])
# output: ' a  b  c '

export function

除了表達式和流程控制,tornado還給template提供了很多導出函數,可以在template裏面直接使用,譬如最常使用的escape等,同時,我們還可以將函數傳遞給template,如下:

Template("{{ escape(url) }}").generate(url = 'a=1&b=2')
# output: 'a=1&amp;amp;b=2'

Template("{{ l(data) }}").generate(data = [1,2,3], l = lambda data: [ 2 * d for d in data ])
# output: '[2, 4, 6]'

inheritance

tornado的template支持繼承,也就是說,我們可以通過繼承一個基本的模板,然後再在子模板裏面定製需要的東西。這個就跟c++裏面多態一樣。很是強大。

tornado的template通過extends和block來進行模板的繼承。

#定義一個基本模板 main.html
<header>
{{% block header %}}{{% end %}}
</header>

#定義子模板 index.html
{{% extends main.html %}}}
{{% block header %}} <h1>Hello world!</h1>
{{% end %}}

可以看到,template的繼承很簡單,我們在base模板裏面定義整體的模板框架,使用block字段來標明子模板可以重載。子模板通過extends載入base模板,然後使用block來定製自己的功能。

UIModule

從上面可以看到,tornado的template雖然簡單,但是卻很強大,不光如此,tornado還提供了UIModule,讓我們更強大的去定製自己的html頁面。在編寫不同的web頁面的時候,有時候我們需要重用一些html代碼,這種情況不適用extends和block,如果以c++對比,extends和block就如同類的繼承,是類的複用,而我們這裏則需要實現的是函數級別的複用。

幸運的是,tornado的UIModule提供了這種功能,我們首先繼承UIModule,然後將其註冊給application,這樣模板就能使用這個UIModule了,如下:

class HelloModule(tornado.web.UIModule): 
    def render(self):
        return '<h1>Hello, world!</h1>'

app = tornado.web.Application(
    ui_modules={'Hello', HelloModule}
)

#我們註冊了一個Hello的UIModule,這樣template就可以使用了,index.html
<html>
<body>
    {{% module Hello() %}} 
</body>
</html>

可以看出,uimodule的使用也很簡單,更強大的是,我們可以在uimodule裏面嵌入自己的css,javascript等。只需要重載繼承的embedded_javascript,embedded_css等,這裏就不展開了。

後面的話

tornado的template是一個很強大的模塊,使用它,我們可以快速構建web應用,不過,我們仍然可以使用其他的模板引擎來與tornado集成,這裏不得不說tornado的強大。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章