Tornado之实例和扩展
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的扩展
- 定义的每个handler都会继承RequestHandler,RequestHandler在init方法后都会调用initialize方法,并未实现。这是一个hook,所以我们可以扩展实现更为强大的功能
- 深度继承的扩展
深度继承样例
#!/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()