1. 程式人生 > >Tornado之實例和擴展

Tornado之實例和擴展

import play sta tin oct con acc type containe

1、Tornado文件的結構:

  1、Controllers控制器

  2、Models數據庫操作

  3、Views前端顯示

技術分享

2、樣例

app

#!/usr/bin/env python
# -*- coding: utf8 -*-
from tornado.ioloop import IOLoop
from tornado.web import Application
import tornado

import tornado.ioloop
import tornado.web
# 從controllers導入別的handlers
from controllers.account import
LoginHandler from controllers.home import HomeHandler # 實例化一個Mainhandler來處理主頁 class MainHandler(tornado.web.RequestHandler): def get(self): # self.write("Hello, world") # self.render("main.html") self.redirect(http://www.baidu.com) # 用戶可以自定義方法在前端使用 import
uimethods as mt # 用戶可以自定義類在前端使用 import uimodules as mm from tornado import escape # 將一些額外的參數傳遞給application settings = { "template_path": views, cookie_secret: asdfpojaksdfyknasdfklasdf, ui_methods: mt, ui_modules: mm, static_path: static, } # 實例化一個application
application = tornado.web.Application([ (r"/index", MainHandler), (r"/login", LoginHandler), (r"/home", HomeHandler), ], **settings) if __name__ == "__main__": # 綁定端口 application.listen(8888) # 啟動服務 tornado.ioloop.IOLoop.instance().start()

前端樣例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ tab(11) }}  <!-- 自定義方法 -->
    {% raw tab(11) %}  <!-- 將tab(11)的結果不轉義,該怎麽顯示就顯示 -->

    {% module Custom(22) %}  <!-- 調用用戶的自定義類 -->

    <form action="/login" method="POST">
        <input type="text" name="user"/>
        <input type="password" name="pwd"/>
        <input type="submit" value="提交" />{{msg}}  <!-- 變量 -->
    </form>
</body>
</html>

UImethod

from tornado import escape
def tab(request,val):
    # 返回一段代碼,會自動渲染成相應的內容
    return <h1>Hello World!</h1>

UIModule

from tornado.web import UIModule
from tornado import escape

class Custom(UIModule):
    def css_files(self):
        # 會在head部加上css樣式文件
        return "commons.css"
        # 會在頭部嵌入相應的css
    def embedded_css(self):
        return ".c1{display:none}"
        # 會在body的底部,加上js文件
    def javascript_files(self):
        return "commons.js"
    def embedded_javascript(self):
        # 會在body的底部,加上js代碼
        return "function f1(){alert(123);}"
    def render(self, val):
        # return "老村長" # 渲染相應的內容
        # return ‘<h1>老村長</h1>‘ # 渲染相應的內容,但是默認會轉義
        v = escape.xhtml_escape(<h1>老村長</h1>) # 不轉義,前端必須加上raw
        return v

3、Tornado的擴展

  1. 定義的每個handler都會繼承RequestHandler,RequestHandler在init方法後都會調用initialize方法,並未實現。這是一個hook,所以我們可以擴展實現更為強大的功能
  2. 深度繼承的擴展

深度繼承樣例

#!/usr/bin/env python
# -*- coding: utf8 -*-
import tornado.ioloop import tornado.web from controllers.account import LoginHandler from controllers.home import HomeHandler class Foo(tornado.web.RequestHandler): def initialize(self): self.A = 123 self.set_cookie(ag) # 調用其父類的initialize,把實例化對象傳過來給Foo的父類的構造器 super(Foo,self).initialize() class MainHandler(Foo): # 可以利用深度繼承,來做一些進一步的封裝,註意傳給父類的self是自身的實例化對象 def get(self): print(self.A) self.write("Hello, world") application = tornado.web.Application([ (r"/index", MainHandler), ]) if __name__ == "__main__": application.listen(9999) tornado.ioloop.IOLoop.instance().start()

3、Tornado只支持cookie,我們對其作進一步擴展,使其支持session功能

給Tornado添加session模塊

#!/usr/bin/env python
# -*- coding: utf8 -*-
import tornado.ioloop
import tornado.web
from controllers.account import LoginHandler
from controllers.home import HomeHandler

import time
import hashlib

# 內存存儲
class Cache(object):
    """
    將session保存在內存
    """
    def __init__(self):
        self.container = {}

    def __contains__(self, item):
        return item in self.container

    def initial(self,random_str):
        self.container[random_str] = {}

    def get(self,random_str,key):
        return self.container[random_str].get(key)

    def set(self,random_str,key,value):
        self.container[random_str][key] = value

    def delete(self,random_str,key):
        del self.container[random_str][key]

    def open(self):
        pass

    def close(self):
        pass

    def clear(self,random_str):
        del self.container[random_str]

# MemCache存儲,暫未實現,用戶可自己寫此類
class Memcache(object):
    def __init__(self):
        pass

    def get(self,key):
        pass

    def set(self,key,value):
        pass

    def delete(self,key):
        pass

    def open(self):
        pass

    def close(self):
        pass

# Redis存儲,暫未實現,用戶可自己寫此類
class Redis(object):
    def __init__(self):
        pass

    def get(self, key):
        pass

    def set(self, key, value):
        pass

    def delete(self, key):
        pass

    def open(self):
        pass

    def close(self):
        pass

# 用戶可自定義session的存儲方式
P = Cache

class Session(object):
    def __init__(self,handler):
        self.handler = handler
        self.random_str = None
        self.session_db = P()  # 實例化配置對應的存儲類型
        self.session_db.open()
        # 去用戶請求信息中獲取session_id,如果沒有,新用戶
        client_random_str = self.handler.get_cookie(session_id)
        if not client_random_str:
            "新用戶"
            self.random_str = self.create_random_str()
            self.session_db.initial(self.random_str)
        else:
            if client_random_str in self.session_db:
                "老用戶"
                self.random_str = client_random_str
            else:
                "非法用戶"
                self.random_str = self.create_random_str()
                self.session_db.initial(self.random_str)
        ctime = time.time()
        self.handler.set_cookie(session_id,self.random_str,expires=ctime+1800)
        self.session_db.close()

    def create_random_str(self):
        """
        專業創建隨機字符串,基於時間,大家可以加點鹽
        :return: 
        """
        v = str(time.time())
        m = hashlib.md5()
        m.update(bytes(v,encoding=utf-8))
        return m.hexdigest()

    def __setitem__(self, key, value):
        """
        更新用戶cookie對應的session內容,可實現session[‘uuuuu‘]
        :param key: 
        :param value: 
        :return: 
        """
        self.session_db.open()
        self.session_db.set(self.random_str,key,value)
        self.session_db.close()
    def __getitem__(self, key):
        """
        獲取用戶cookie對應的session內容,可實現session[‘uuuuu‘]
        :param key: 
        :return: 
        """
        self.session_db.open()
        v = self.session_db.get(self.random_str,key)
        self.session_db.close()
        return v
    def __delitem__(self, key):
        """
        刪除用戶cookie對應的session內容
        :param key: 
        :return: 
        """
        
        self.session_db.open()
        self.session_db.delete(self.random_str,key)
        self.session_db.close()

    def clear(self):
        """
        清空用戶cookie對應的session內容
        :return: 
        """
        
        self.session_db.open()
        self.session_db.clear(self.random_str)
        self.session_db.close()

class SessionHandler(object):
    def initialize(self):
        # self是MainHandler對象
        self.session = Session(self) # 會把當前實例化的對象傳進去
        super(SessionHandler,self).initialize() # 利用python的廣度繼承

class HomeHandler(SessionHandler,tornado.web.RequestHandler):
    """
    SessionHandler應該放在左邊,因為SessionHandler利用了python的廣度繼承
    如果覺得麻煩可讓SessionHandler繼承RequestHandler,使其成為深度繼承
    """
    def get(self):
        # 根據用戶的cookie
        user = self.session[username]
        if not user:
            self.redirect("http://www.oldboyedu.com")
        else:
            self.write(user)

class LoginHandler(SessionHandler,tornado.web.RequestHandler):
    # 登錄的時候可根據表單提交,完成相應的增刪改查
    def get(self):
        self.session[uuuuu] = root
        self.redirect(/home)

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.set_cookie(k1, vvv, expires=time.time()+20)

class ShowHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(self.get_cookie(k1))



application = tornado.web.Application([
    (r"/login", LoginHandler),
    (r"/home", HomeHandler),
    (r"/test", TestHandler),
    (r"/show", ShowHandler),
])

if __name__ == "__main__":
    application.listen(9999)
    tornado.ioloop.IOLoop.instance().start()

Tornado之實例和擴展