一. 在 tornado模板中使用自定義方法
在tornado中可以使用兩種方式,達到在模板中調用自定義方法的效果,第一種是使用UIMethod 和UIModule。
1.UIMethod使用方法示例如下:
(1)在項目中建立一個新py文件命名為uimethod:

需要注意的是,這里的函數都需要加一個參數self,否則會報錯
1 def show(self): 2 return "1111" 3 4 def lower_case(self, arg): 5 return arg.lower()
原因是這里的函數,其實本質上是渲染模板的handler類的方法,如下圖中debug時候跟蹤的結果所示,self其實就是MainHandler的實例

(2)在程序入口文件中引入並注冊settings(key為ui_methods):
1 import uimethods as mt 2 3 # 其他的部分略... 4 5 settings = { 6 'template_path': 'template', 7 'static_path': 'static', 8 'static_url_prefix': '/static/', 9 'ui_methods': mt, 10 }
(3)在模板中使用方法:

注意這里調用lower_case處的入參test,是必須在render模板的時候,傳入方法的,否則就是未定義,和其他直接在模板里使用的變量相同:
1 class MainHandler(tornado.web.RequestHandler): 2 @asynchronous 3 @gen.coroutine 4 def get(self): 5 is_authed = (self.get_cookie('auth', None) == USER) 6 self.render('index.html', is_authed=is_authed, user_id=self.get_cookie('auth', None), contents=CONTENTS, test='AA')
2. UIModule使用方法示例如下:
(1)創建文件

UIModule就是自定義類繼承UIModule,其方法render返回的內容在模板上調用類的時候會被顯示
1 from tornado.web import UIModule 2 from tornado import escape 3 4 class showMod(UIModule): 5 6 def render(self, *args, **kwargs): 7 return escape.xhtml_escape('333')
(2)在程序入口文件中引入並注冊settings(key為ui_mothods):
1 import uimethods as mt 2 3 settings = { 4 'template_path': 'template', 5 'static_path': 'static', 6 'static_url_prefix': '/static/', 7 'ui_methods': mt, 8 'ui_modules': md, 9 }
(3)在模板中使用:

3. 然后小記一點tornado模板實現的原理:


實際上就是把模板的html,先根據{{與{%等特殊字符分割,將這些特殊部分外的字符串與特殊字符內的內容進行拼接;特殊字符內的字符串會經過一些特殊處理,比如獲取變量判斷類型,做python的邏輯判斷或者是循環或者是函數調用等等,然后這些運算結果與其他部分進行拼接。拼接的方式是生成如左圖這樣一個函數的字符串,該函數作用是將內容根據我之前說的步驟,append到_buffer的列表里。然后把這個字符串用compile和exec即可編譯執行。
對於函數中的參數如"title","data",是將render方法里面傳入的參數,作為namespace全局變量加入exec里面,這樣來實現的,簡單的模擬如下:

4. tornado當中還提供了一寫內置模板方法(其實也是用UIMothod,UIModule)實現的,小計如下:
- escape: tornado.escape.xhtml_escape 的別名
- xhtml_escape: tornado.escape.xhtml_escape 的別名
- url_escape: tornado.escape.url_escape 的別名
- json_encode: tornado.escape.json_encode 的別名
- squeeze: tornado.escape.squeeze 的別名
- linkify: tornado.escape.linkify 的別名
- datetime: Python 的 datetime 模組
- handler: 當前的 RequestHandler 對象
- request: handler.request 的別名
- current_user: handler.current_user 的別名
- locale: handler.locale 的別名
- _: handler.locale.translate 的別名
- static_url: for handler.static_url 的別名
- xsrf_form_html: handler.xsrf_form_html 的別名
二. static_path 和 static_url_prefix配置
在tornado的settings當中,有兩個非必選參數 static_path和static_url_prefix,用來簡化關於靜態文件獲取的方法。使用實例如下:

1. static_path 默認值為 static,也就是配置的所有靜態文件的根目錄,然后在模板或css中尋找文件路徑的時候,就不用都自己去做一寫絕對路徑的配置寫法了,方便統一管理修改,tornado就回到這里去找靜態文件。只需要在模板中使用方法static_url,就會自動生成訪問靜態文件的相對路徑,使用示例如下:

結果轉換出來的是:

可以看到自動在css前面加了static,后面的v=XXXXXXXX則是static_url的另外個功能即讓瀏覽器生成緩存記錄
2.static_url_prefix 默認值為 /static/, 配置的是模板方法 static_url 里生成的結果里面 ,比如上面那個例子里面,就是/static/css前面的這個static,是可以改掉的,url就會不同。不過改這個不影響去找靜態文件的存儲路徑也就是static_path
三. tornado中對cookie的一些操作
1. tornado中設置cookie示例:
1 self.set_cookie('auth', user_id, expires_days=30)
前兩個分別是cookie鍵和值,后面的expires_days是可選參數,設置過期時間。如果我們想操作用戶登出以后的cookie失效,可以改成expires_days=0。此外set_cookie還有個重要的可選參數是path,可以指定路徑,這個cookie就會只能在指定的路徑(路由頁面)生效。
2. 獲取cookie示例:
1 self.get_cookie('auth', None)
3. 給cookie加鹽示例:
tornado中的set_cookie和get_cookie是明文不加密傳輸的,set_secure_cookie和get_secure_cookie是明文加密傳輸的,使用后兩者的方法與前兩者相同,只是需要在settings里面多加一點,在tornado.web.Application中設置cookie_secret參數:

也就是為其加鹽!此外如果我們看一下set_secure_cookie的源碼,會發現其expires_days默認值為30,而set_cookie的默認值為None...也就是注意用了set_secure_cookie以后默認就會持續30天的,而且還發現set_secure_cookie當中並沒有path這個可選參數哦。
4. 此外RequestHandler 的cookies(示例用self.cookies)屬性是獲得所有cookie。
四. 對ajax發送的數據中含有中文的處理
在嘗試使用ajax向tornado后端發post請求時候,我發現發送的data里面帶有非拉丁字符的話,tornado在獲取是會產生錯誤,無法正確地用get_argument取到參數

這個時候可以使用js的“encodeURI”方法來進行編碼,示例如下:
1 var params = "article=" + encodeURI(text) + "&group=" + encodeURI(group);
這樣在py3的tornado中使用get_argument時候就能正確獲取了,而且也不用特意再decode。
