Tornado全称Tornado Web Server,是一个用Python语言写成的Web服务器兼Web应用框架,由FriendFeed公司在自己的网站FriendFeed中使用,被Facebook收购以后框架以开源软件形式开放给大众。
主要分为两个部分,一个是application,另一个是RequestHandler的子类们.
负责全局配置, 包括映射请求转发给处理程序的路由表。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服务关闭。
可以理解为就是tornado的view,
class IndexNonTemplateHandler(CommonHandler):
"""
不带模板的handler
"""
def get(self, *args, **kwargs):
self.write(
'''
Hello Tornado
我要尝试一下中文
'''
)
RequestHandler的结构比较简单,就是根据不同的http方法写不同的函数。返回内容有两种方式:
self.write(content)
将内容写入返回self.render('index.html', greet=u'我只是传来的一句问候语')
返回模板内容,其中模板的路径是在Application的template_path定义的,而传参和django有一丢丢区别,django的context是传一个字典,而这里是传普通参数。关于404和500页面处理的方法分别是:
def write_error(self, status_code, **kwargs)
方法,可返回字符串或者template好的,并没有,嘻嘻。
get_current_user
方法,开发者可以重写这个方法,返回一个可用的用户对象,就可以在相关view函数中通过self.current_user
获取。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。
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")