安装:
pip3 install tornado 源码安装 https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
简单入手
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") application = tornado.web.Application([ (r"/index", MainHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
import tornado.ioloop import tornado.web from tornado import httpclient from tornado.web import asynchronous from tornado import gen # import uimodules as md # import uimethods as mt class MainHandler(tornado.web.RequestHandler): @asynchronous @gen.coroutine #没测出来效果(这两个装饰器) def get(self): print('start get ') http = httpclient.AsyncHTTPClient() http.fetch("https://www.google.com/", self.callback) #利用fetch发送一个异步请求(挂起) self.write('end') def callback(self, response): print(response.body,"---") settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', # 'ui_methods': mt, # 'ui_modules': md, } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8009) tornado.ioloop.IOLoop.instance().start()
配置静态路径
settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'sfdsfsdfsdf', #用于给cookie加密的秘钥
}
加密cookie
签名Cookie的本质是:
写cookie过程:
- 将值进行base64加密
- 对除值以外的内容进行签名,哈希算法(无法逆向解析)
- 拼接 签名 + 加密值
读cookie过程:
- 读取 签名 + 加密值
- 对签名进行验证
- base64解密,获取值内容
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): login_user = self.get_secure_cookie("login_user", None) if login_user: self.write(login_user) else: self.redirect('/login') class LoginHandler(tornado.web.RequestHandler): def get(self): self.current_user() self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): username = self.get_argument('name') password = self.get_argument('pwd') if username == 'root' and password == '123': self.set_secure_cookie('login_user', '武沛齐') self.redirect('/') else: self.render('login.html', **{'status': '用户名或密码错误'}) settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh' } application = tornado.web.Application([ (r"/index", MainHandler), (r"/login", LoginHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
import tornado.ioloop import tornado.web class BaseHandler(tornado.web.RequestHandler): def get_current_user(self): return self.get_secure_cookie("login_user") class MainHandler(BaseHandler): @tornado.web.authenticated def get(self): login_user = self.current_user self.write(login_user) class LoginHandler(tornado.web.RequestHandler): def get(self): self.current_user() self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): username = self.get_argument('name') password = self.get_argument('pwd') if username == 'wupeiqi' and password == '123': self.set_secure_cookie('login_user', '武沛齐') self.redirect('/') else: self.render('login.html', **{'status': '用户名或密码错误'}) settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 'login_url': '/login' } application = tornado.web.Application([ (r"/index", MainHandler), (r"/login", LoginHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
CSRF
settings = { "xsrf_cookies": True, } application = tornado.web.Application([ (r"/", MainHandler), (r"/login", LoginHandler), ], **settings)
<form action="/new_message" method="post"> {{ xsrf_form_html() }} <input type="text" name="message"/> <input type="submit" value="Post"/> </form>
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 + ")")); }}); };
注:Ajax使用时,本质上就是去获取本地的cookie,携带cookie再来发送请求
上传文件
form表单上传
<form id="my_form" name="form" action="/index" method="POST" enctype="multipart/form-data" > <input name="fff" id="my_file" type="file" /> <input type="submit" value="提交" /> </form>
def post(self, *args, **kwargs): file_metas = self.request.files["fff"] # print(file_metas) for meta in file_metas: file_name = meta['filename'] with open(file_name,'wb') as up: up.write(meta['body'])
ajax上传
<body> <input type="file" id="img" /> <input type="button" onclick="UploadFile();" /> <script> function UploadFile(){ var fileObj = document.getElementById("img").files[0]; var form = new FormData(); form.append("k1", "v1"); form.append("fff", fileObj); var xhr = new XMLHttpRequest(); xhr.open("post", '/index', true); xhr.send(form); } </script> </body>
<body> <input type="file" id="img" /> <input type="button" onclick="UploadFile();" /> <script> function UploadFile(){ var fileObj = $("#img")[0].files[0]; var form = new FormData(); form.append("k1", "v1"); form.append("fff", fileObj); $.ajax({ type:'POST', url: '/index', data: form, processData: false, // tell jQuery not to process the data contentType: false, // tell jQuery not to set contentType success: function(arg){ console.log(arg); } }) } </script> </body>
验证码
待处理
异步非阻塞
class AsyncHandler(tornado.web.RequestHandler): @gen.coroutine def get(self): future = Future() future.add_done_callback(self.doing) yield future # 或 # tornado.ioloop.IOLoop.current().add_future(future,self.doing) # yield future def doing(self,*args, **kwargs): self.write('async') self.finish()
httpclient类库
Tornado提供了httpclient类库用于发送Http请求,其配合Tornado的异步非阻塞使用。
import tornado.web from tornado import gen from tornado import httpclient # 方式一: class AsyncHandler(tornado.web.RequestHandler): @gen.coroutine def get(self, *args, **kwargs): print('进入') http = httpclient.AsyncHTTPClient() data = yield http.fetch("http://www.google.com") print('完事',data) self.finish('6666') # 方式二: # class AsyncHandler(tornado.web.RequestHandler): # @gen.coroutine # def get(self): # print('进入') # http = httpclient.AsyncHTTPClient() # yield http.fetch("http://www.google.com", self.done) # # def done(self, response): # print('完事') # self.finish('666') application = tornado.web.Application([ (r"/async", AsyncHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
session组件(原创)
import tornado.web import tornado.ioloop import time,hashlib content = { } class Session: def create_random_string(self): nid = time.time() hash_lib = hashlib.md5() hash_lib.update(bytes(str(nid), encoding="utf8")) return hash_lib.hexdigest() def create_session(self): self.session_id = self.create_random_string() print("chuangjiancookie") self.set_cookie("session_id", self.session_id,expires=time.time()+60*7*24) def add_content(self,session_id): "将session_id添加到content(数据库/本地文件)" self.session_id = session_id content[self.session_id] = {} def add_user(self,username,password): "注册成功过了" content[self.session_id]["username"]=username content[self.session_id]["password"]=password def auth_session(self): "判断用户是否已经登录" session_id = self.get_cookie("session_id") if session_id ==None: self.create_session() return False if session_id not in content: return False else: #每次访问网站就会更新cookie时间 self.set_cookie("session_id",session_id, expires=time.time() + 60 * 5) return True def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs) class HomeHandler(Session,tornado.web.RequestHandler): def get(self, *args, **kwargs): auth = self.auth_session() if auth == False: self.redirect("/login") else: self.write("登录成功") class LoginHandler(Session,tornado.web.RequestHandler): def get(self, *args, **kwargs): # 验证session auth = self.auth_session() if auth ==False: self.render("login.html") if auth == True: self.redirect("/home") def post(self, *args, **kwargs): username = self.get_argument("username") password = self.get_argument("password") session_id = self.get_cookie("session_id") # 从数据库中是否含有root账号,密码是否为password,稍微改一下即可 if username == "root" and password == "1": # 模拟登录成功之后的操作,下面的代码用于注册用户时使用 self.add_content(session_id) self.add_user(username,password) self.redirect("/home") else: self.render("login.html") settings = { "template_path":"template", "cookie_secret":"agcgsd" } application = tornado.web.Application([ (r"/login",LoginHandler), (r"/home",HomeHandler) ],**settings) if __name__=="__main__": application.listen(8000) tornado.ioloop.IOLoop.instance().start()