Tornado 學習筆記 Tornado基礎 2

內容原子官方文檔:


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,有部分無法支持。


界面模塊

界面模塊是一種可重用組件,例如博客的主頁面和內容頁都使用顯示一條博客功能。

定義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_javascriptjavascript_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)


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