介紹
Tornado全稱Tornado Web Server,是一個用Python語言寫成的Web服務器兼Web應用框架,由FriendFeed公司在自己的網站FriendFeed中使用,被Facebook收購以後框架以開源軟件形式開放給大衆。
特點
- 作爲Web框架,是一個輕量級的Web框架,類似於另一個Python web 框架Web.py,其擁有異步非阻塞IO的處理方式。
- 作爲Web服務器,Tornado有較爲出色的抗負載能力,官方用nginx反向代理的方式部署Tornado和其它Python web應用框架進行對比,結果最大瀏覽量超過第二名近40%
web框架使用簡述
結構
主要分爲兩個部分,一個是application,另一個是RequestHandler的子類們.
Application
負責全局配置, 包括映射請求轉發給處理程序的路由表。e.g.
import logging
from tornado.ioloop import IOLoop
from tornado.web import Application
from handlers.errors import DefaultHandler
from handlers.index import (IndexNonTemplateHandler, IndexTemplateHandler, RaiseErrorHandler, EchoWebSocket)
def log_func(handler):
logging.info(handler.request)
settings = {
'log_function': log_func,
'template_path': 'templates',
'default_handler_class': DefaultHandler
}
def make_app():
return Application([
(r'/', IndexNonTemplateHandler),
(r'/index', IndexTemplateHandler),
(r'/raise_error', RaiseErrorHandler),
(r'/echo_websocket', EchoWebSocket),
], **settings)
if __name__ == '__main__':
app = make_app()
app.listen(9723)
IOLoop.current().start()
這些配置裏有個很有趣的地方,tornado的熱重載是可以自己設置的,但是他的熱重載會導致把命令行中斷。需要在後臺如任務管理器等工具中將tornado的web服務關閉。
RequestHandler
可以理解爲就是tornado的view,
class IndexNonTemplateHandler(CommonHandler):
"""
不帶模板的handler
"""
def get(self, *args, **kwargs):
self.write(
'''
<h1>Hello Tornado</h1>
<p>我要嘗試一下中文</p>
'''
)
RequestHandler的結構比較簡單,就是根據不同的http方法寫不同的函數。返回內容有兩種方式:
- 一種是直接調用
self.write(content)
將內容寫入返回 - 另一種是使用
self.render('index.html', greet=u'我只是傳來的一句問候語')
返回模板內容,其中模板的路徑是在Application的template_path定義的,而傳參和django有一丟丟區別,django的context是傳一個字典,而這裏是傳普通參數。
關於404和500頁面處理的方法分別是:
- 404是在application設定默認的RequestHandler,如果找不到則會轉發到這個handler中來。
- 500是需要重寫RequestHandler的
def write_error(self, status_code, **kwargs)
方法,可返回字符串或者template
像django一樣強大的用戶認證系統
好的,並沒有,嘻嘻。
- 不過,他的RequestHandler提供了一個
get_current_user
方法,開發者可以重寫這個方法,返回一個可用的用戶對象,就可以在相關view函數中通過self.current_user
獲取。 - 另外tornado.auth模塊還提供了Google/Gmail, Facebook, Twitter,和FriendFeed.等第三方應用的oauth認證。然而好像並沒有什麼卵用。
- 關於csrf,只需要在Application中設置一下xsrf_cookies就可以使用
template
tornado的模板語法和django的默認模板語法比較相似。不過比較麻煩的是模板複用這個功能,需要在後臺建立一個uimoudle。
class Entry(tornado.web.UIModule):
def render(self, entry, show_comments=False):
return self.render_string(
"module-entry.html", entry=entry, show_comments=show_comments)
然後在Application中設置ui_moudle,接着RequestHandler還得把對應的uimodule以存進context中,最後纔可以在template中用module調用。
from . import uimodules
class HomeHandler(tornado.web.RequestHandler):
def get(self):
entries = self.db.query("SELECT * FROM entries ORDER BY date DESC")
self.render("home.html", entries=entries)
class EntryHandler(tornado.web.RequestHandler):
def get(self, entry_id):
entry = self.db.get("SELECT * FROM entries WHERE id = %s", entry_id)
if not entry: raise tornado.web.HTTPError(404)
self.render("entry.html", entry=entry)
settings = {
"ui_modules": uimodules,
}
application = tornado.web.Application([
(r"/", HomeHandler),
(r"/entry/([0-9]+)", EntryHandler),
], **settings)
數據庫相關
tornado是沒有自帶orm的,還是得引入第三方orm纔可以解決問題。
不過官方開發了個叫torndb的庫,可以方便tornado對數據庫的操作。不過還是隻能寫sql。而且只支持了mysql。
Websocket
tornado有一個特色就是默認支持websocket,實現起來也非常簡單,只需要繼承WebSocketHandler並重寫對應的事件方法即可。e.g.
class EchoWebSocket(WebSocketHandler):
def data_received(self, chunk):
pass
def open(self):
print("WebSocket opened")
def on_message(self, message):
self.write_message(u"You said: " + message)
def on_close(self):
print("WebSocket closed")