內容原子官方文檔:
Tornado基礎
模板和UI
模板可以使用多種模板語言,通過 RequestHandler.render整合到系統中,簡單渲染字符串通過RequestHandler.write
配置模板
默認會在py文件相同目錄查找模板,在其他位置可以使用template_path Application setting 或者覆蓋 RequestHandler.get_template_path 。如果不是文件系統的位置,可以通過 tornado.template.BaseLoader子類並傳入一個template_loader 實例。 模板緩存默認開啓,如果想關閉可以設置compiled_template_cache=False 或者debug=True 。
模板語法
<html> <head> <title>{{ title }}</title> </head> <body> <ul> {% for item in items %} <li>{{ escape(item) }}</li> {% end %} </ul> </body> </html>
調用
class MainHandler(tornado.web.RequestHandler): def get(self): items = ["Item 1", "Item 2", "Item 3"] self.render("template.html", title="My title", items=items)
表達式: 支持RequestHandler.render and render_string,需要用於RequestHandler內,如果使用tornado.template,有部分無法支持。
escape: alias for tornado.escape.xhtml_escape
xhtml_escape: alias for tornado.escape.xhtml_escape
url_escape: alias for tornado.escape.url_escape
json_encode: alias for tornado.escape.json_encode
squeeze: alias for tornado.escape.squeeze
linkify: alias for tornado.escape.linkify
datetime: the Python datetime module
handler: the current RequestHandler object
request: alias for handler.request
current_user: alias for handler.current_user
locale: alias for handler.locale
_: alias for handler.locale.translate
static_url: alias for handler.static_url
xsrf_form_html: alias for handler.xsrf_form_html
reverse_url: alias for Application.reverse_url
All entries from the ui_methods and ui_modules Application settings
Any keyword arguments passed to render or render_string
界面模塊
界面模塊是一種可重用組件,例如博客的主頁面和內容頁都使用顯示一條博客功能。
定義Entry模塊,文件名uimodules.py
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
主程序中設置使用ui_modules。
from . import uimodulesclass 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)
模板的首頁面中調用Entry 模塊
{% for entry in entries %} {% module Entry(entry) %} {% end %}
模板的內容頁調用Entry 模塊
{% module Entry(entry, show_comments=True) %}
模型定義可以使用embedded_css,embedded_javascript, javascript_files, or css_files 方法:
class Entry(tornado.web.UIModule): def embedded_css(self): return ".entry { margin-bottom: 1em; }" def render(self, entry, show_comments=False): return self.render_string( "module-entry.html", show_comments=show_comments)
或者直接定義在模板中
{{ set_resources(embedded_css=".entry { margin-bottom: 1em; }") }} <!-- more template html... -->
調用帶有嵌入內容的模板
{% module Template("module-entry.html", show_comments=True) %}
授權和安全
配置加密cookie
application = tornado.web.Application([ (r"/", MainHandler), ], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
可以使用 set_secure_cookie and get_secure_cookie方法使用加密cookie。
class MainHandler(tornado.web.RequestHandler): def get(self): if not self.get_secure_cookie("mycookie"): self.set_secure_cookie("mycookie", "myvalue") self.write("Your cookie was not set yet!") else: self.write("Your cookie was set!")
用戶授權
當前已授權的用戶會保持在請求處理器的self.current_user中,並且在模板變量current_user中。
下面是使用加密cookie保存數據方式的用戶登錄授權實例:
class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("user")class MainHandler(BaseHandler): def get(self): if not self.current_user: self.redirect("/login") return name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name)class LoginHandler(BaseHandler): def get(self): self.write('<html><body><form action="/login" method="post">' 'Name: <input type="text" name="name">' '<input type="submit" value="Sign in">' '</form></body></html>') def post(self): self.set_secure_cookie("user", self.get_argument("name")) self.redirect("/")application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler),], cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__")
可以通過 tornado.web.authenticated裝飾器使用授權狀態。
class MainHandler(BaseHandler): @tornado.web.authenticated def get(self): name = tornado.escape.xhtml_escape(self.current_user) self.write("Hello, " + name)settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login",}application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler),], **settings)
XSRF
啓用XSRF
settings = { "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", "xsrf_cookies": True,}application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler),], **settings)
使用XSRF在普通表單
<form action="/new_message" method="post"> {% module xsrf_form_html() %} <input type="text" name="message"/> <input type="submit" value="Post"/> </form>
使用XSRF在AJAX中
function getCookie(name) { var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); return r ? r[1] : undefined; } jQuery.postJSON = function(url, args, callback) { args._xsrf = getCookie("_xsrf"); $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST", success: function(response) { callback(eval("(" + response + ")")); }}); };
啓動服務
def main(): app = make_app() app.listen(8888) IOLoop.current().start()if __name__ == '__main__': main()
使用多核CPU
def main(): app = make_app() server = tornado.httpserver.HTTPServer(app) server.bind(8888) server.start(0) # forks one process per cpu IOLoop.current().start()
靜態目錄設置
settings = { "": os.path.join(os.path.dirname(__file__), "static"), "cookie_secret": "__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", "login_url": "/login", "xsrf_cookies": True,} application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), (r"/(apple-touch-icon\.png)", tornado.web.StaticFileHandler, dict(path=settings['static_path'])),], **settings)
嵌入到WSGI容器運行
嵌入到WSGI容器後,只可以運行tornado的一個子集功能,不支持異步操作,包括協程、@asynchronous裝飾器、AsyncHTTPClient, the auth module, and WebSockets.
import tornado.webimport tornado.wsgiclass MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world")tornado_app = tornado.web.Application([ (r"/", MainHandler),])application = tornado.wsgi.WSGIAdapter(tornado_app)