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)


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