Tornado Web框架
一、初识tornado web框架
1、tornado静态文件和模板路径的配置
tornado不同于其他所有的web框架,tornado是python唯一一款使用epoll,异步IO,高并发的web框架,首先看一下下面一段代码,开启tornado的学习之旅;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "charles" import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): # self.write("Hello, world") self.render("s1.html") def post(self, *args, **kwargs): #表单以post方式提交 self.write("hello world") settings = { "template_path":"template", #模版路径的配置 "static_path":'static', #静态文件配置 } #路由映射,路由系统 application = tornado.web.Application([ #创建对象 (r"/index", MainHandler), ],**settings) #将settings注册到路由系统,这样配置才会生效 if __name__ == "__main__": application.listen(8888) #创建socket,一直循环 tornado.ioloop.IOLoop.instance().start() #使用epoll,io多路复用
对于静态文件配置,除了上述setttings的设置之外,还需要在模板语言中引入静态文件的时候这么下,看下面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="static/commons.css"> </head> <body> <h1>s1</h1> <script src="static/oldboy.js"></script> </body> </html>
2、tornado模板语言
tornado模板语言在views中render向模板语言传入的参数是列表
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "charles" import tornado.ioloop import tornado.web INPUT_LIST=[] class MainHandler(tornado.web.RequestHandler): def get(self): # self.write("Hello, world") self.render("s1.html",xxxooo=INPUT_LIST) def post(self, *args, **kwargs): #表单以post方式提交,客户端post之后,服务端执行该方法 print("post") name = self.get_argument('xxx') #获取post的值 INPUT_LIST.append(name) print(name) self.render("s1.html",xxxooo=INPUT_LIST) settings = { "template_path":"template", #模版路径的配置 "static_path":'static', #静态文件配置
"static_url_prefix":"/sss/" #静态文件前缀,只做显示使用 } #路由映射,路由系统 application = tornado.web.Application([ #创建对象 (r"/index", MainHandler), ],**settings) if __name__ == "__main__": application.listen(8888) #创建socket,一直循环 tornado.ioloop.IOLoop.instance().start() #使用epoll,io多路复用
html模板语言的内容如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="static/commons.css"> </head> <body> <h1>提交内容</h1> <form method="post" action="/index" > <input type="text" name="xxx" /> <input type="submit" value="提交" /> </form> <h1>展示内容:</h1> <ul> {% for item in xxxooo %} <li>{{item}}</li> {% end %} </ul> <script src="static/oldboy.js"></script> </body> </html>
3、Tornado之自定义UIMethod和UIModule
a、使用get提交
在上面的例子中,我们是使用form+post提交数据的,那么可不可以使用get方式提交数据呢?看下面
首先在浏览器中输入内容:http://127.0.0.1:8888/index?name=123&age=18
服务端get方法如下:
class MainHandler(tornado.web.RequestHandler): def get(self): print(self.get_argument('name'),) print(self.get_argument('age'))
这样就通过get方式提交数据到了后台,或者我们也可以在form中,将method设置为get,也可以提交数据;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="static/commons.css"> </head> <body> <h1>提交内容</h1> <form method="get" action="/index" > <input type="text" name="name" /> <input type="submit" value="提交" /> </form> <h1>展示内容:</h1> <h3>{{NPM}}</h3> <ul> {% for item in xxxooo %} <li>{{item}}</li> {% end %} </ul> <script src="static/oldboy.js"></script> </body> </html>
此时就只需要get方法就可以获取和提交数据了
import tornado.ioloop import tornado.web INPUT_LIST=[] class MainHandler(tornado.web.RequestHandler): def get(self): # self.write("Hello, world") name = self.get_argument('name',None) #为防止出错,必须这么写 if name: INPUT_LIST.append(name) self.render("s1.html",NPM='npm',xxxooo=INPUT_LIST)
b、 uimethod和uimodule(自定义模板语言)
上面我们使用的是又有的模板语言,如果想要自定义内容显示的话,可以使用函数和类的方式,显示我们自定义的内容;
uimethod使用函数,将写好的函数传入模板语言,来显示我们需要显示的内容;
(1)定义需要传入的函数,uimothod.py
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "charles" def func(self,args): print(args) return args.lower()
(2)函数导入并注册
import tornado.ioloop import tornado.web import uimethod as mt settings = { "template_path":"template", #模版路径的配置 "static_path":'static', #静态文件配置 'ui_methods':mt, 'ui_modules':md, }
(3)应用(在模本语言中)
<h3>{{func(NPM)}}</h3>
uimodule和uimothod类似
(1)定义需要传入的类
from tornado.web import UIModule from tornado import escape class custom(UIModule): def render(self, *args, **kwargs): return '1234'
(2)函数导入并注册
import uimodule as md settings = { "template_path":"template", #模版路径的配置 "static_path":'static', #静态文件配置 'ui_methods':mt, 'ui_modules':md, }
(3)在模本中引用
<h3>{% module custom() %}</h3>
4、tornado之内置模板方法
在模板中默认提供了一些函数、字段、类以供模板使用:
escape: tornado.escape.xhtml_escape 的別名 #做转义 xhtml_escape: tornado.escape.xhtml_escape 的別名 url_escape: tornado.escape.url_escape 的別名 json_encode: tornado.escape.json_encode 的別名 #json处理 squeeze: tornado.escape.squeeze 的別名 linkify: tornado.escape.linkify 的別名 #生产a标签的 datetime: Python 的 datetime 模组 handler: 当前的 RequestHandler 对象 #当前的self request: handler.request 的別名 #request=self.request current_user: handler.current_user 的別名 #handler=self,self.current_user locale: handler.locale 的別名 #self.locals()当前所有的局部变量 _: handler.locale.translate 的別名 static_url: for handler.static_url 的別名 #当前静态文件路径'{{static_url("commons.css")}}',可以不用加前缀,在网页中查看css静态文件,可以看到文件的md5值; xsrf_form_html: handler.xsrf_form_html 的別名 #防止xss攻击
5、tornado之模板引擎本质
通过字符串拼接,拼接生函数的字符串-->全局定义需要传入的参数-->compile()编译字符串--->exec执行函数,并传入参数--->输出函数执行结果;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "charles" namespaces = {'name':'charles','data':[11,22,33]} code ='''def hellocute():return "name %s,age %d" %(name,data[0])''' func = compile(code,'<string>','exec') exec(func,namespaces) result = namespaces["hellocode"]() print(result)
二、Tornado之抽屉新热榜
向tornado模板中传参数,可以有,有如下几种形式:
INPUT_LIST=[]
USER_INFO={'is_login':None}
NEW_LIST= [
{'title':'xxxx',"content":"ccccc"},
{"title":'ddddd',content":'vvvvv'}
]
在版本语言中,对于字典,可以直接使用字典的索引的方式获取值;
实现功能:莫泰对话框登录,登录成功之后发布;
三、Tornado之cookie
1、只有登录成功的时候,才可以访问管理页面,可以通过cookie实现啦;
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = "charles" import tornado.ioloop import tornado.web INPUT_LIST=[] class IndexHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') class LoginHandler(tornado.web.RequestHandler): def get(self): self.render('login.html',status_text="") def post(self, *args, **kwargs): username = self.get_argument('username',None) pwd = self.get_argument('password',None) if username == 'alex' and pwd == '123':
r = time.time()+10 #设置超时时间
self.set_cookie('auth','1',expire=r) #设置cookie的值为1 self.redirect('/manager') else: self.render('login.html',status_text="登录失败") class ManagerHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): co = self.get_cookie('auth') #获取cookie的值 if co == '1': self.render('manager.html') else: self.redirect('/login') def post(self, *args, **kwargs): self.render('manager.html') class LogoutHandler(tornado.web.RequestHandler): def get(self, *args, **kwargs): co = self.get_cookie('auth','0') self.redirect('/login') settings = { "template_path":"views", #模版路径的配置 #"static_path":'statics', #静态文件配置 } #路由映射,路由系统 application = tornado.web.Application([ #创建对象 (r"/index", IndexHandler), (r"/login", LoginHandler), (r"/manager", ManagerHandler), ],**settings) if __name__ == "__main__": application.listen(8888) #创建socket,一直循环 tornado.ioloop.IOLoop.instance().start() #使用epoll,io多路复用
设置cookie的超时时间:
class LoginHandler(tornado.web.RequestHandler): def get(self): self.render('login.html',status_text="") def post(self, *args, **kwargs): username = self.get_argument('username',None) pwd = self.get_argument('password',None) auto = self.get_argument('auto',None) if username == 'alex' and pwd == '123': if auto: self.set_cookie('auth','1',expires_days=7) else: r = time.time()+10 self.set_cookie('auth','1',expires=r) self.redirect('/manager') else: self.render('login.html',status_text="登录失败")
四、tornado简单实例