Tornado基本应用
Posted 青山应回首
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tornado基本应用相关的知识,希望对你有一定的参考价值。
Tornado简介
Tornado有自己的socket(异步非阻塞,原生支持WebSocket),Django没有。
Tornado的模板语言更接近Python风格,比Django要好理解。
Demo示例
from tornado import ioloop from tornado.web import RequestHandler,Application class IndexHandler(RequestHandler): def get(self): self.write("Hello, world") application = Application([ (r"/index", IndexHandler), ]) if __name__ == "__main__": application.listen(8888) ioloop.IOLoop.instance().start()
Tornado路由系统以及通过别名反向生成url
from tornado import ioloop from tornado.web import RequestHandler,Application class IndexHandler(RequestHandler): def get(self): url1 = self.application.reverse_url(\'alias_name1\') url2 = self.application.reverse_url(\'alias_name2\',666) print(url1) print(url2) self.write("Hello, world") class HomeHandler(RequestHandler): def get(self,uid): print(uid) self.write("Hello, Home") application = Application([ (r"/index", IndexHandler,{},\'alias_name1\'), (r"/home/(\\d+)", HomeHandler,{},\'alias_name2\'), ]) # 支持通过域名进行匹配,域名匹配到然后再匹配 url # application.add_handlers("blog.standby.pub",[ # (r"/index", IndexHandler), # (r"/home/(\\d+)", HomeHandler), # ]) if __name__ == "__main__": application.listen(80) ioloop.IOLoop.instance().start()
种子管理系统
路由系统
多种方式实现登录验证
cookie
xsrf
UImethod 和 UImodule
模板引擎
目录结构
tree /f │ app.py │ my_uimethod.py │ my_uimodule.py │ ├─controllers │ account.py │ seed.py │ __init__.py │ │ ├─statics │ commons.css │ footer.css │ ├─tpl footer.html layout.html login.html seed.html video.html
app.py
from controllers.account import * from controllers.seed import * import my_uimethod import my_uimodule settings = { \'template_path\':\'tpl\', \'static_path\':\'statics\', \'static_url_prefix\':\'/static/\', \'xsrf_cookies\': True, # csrf配置 \'cookie_secret\':\'asahcaoclacnqwncakcnal\', \'login_url\':\'/login.html\', \'ui_methods\':my_uimethod, \'ui_modules\':my_uimodule, } application = Application([ (r"/login.html", LoginHandler,{},\'login\'), (r"/logout.html", LogoutHandler,{},\'logout\'), (r"/seed.html", SeedHandler,{},\'seed\'), (r"/video.html", VideoHandler,{},\'video\'), ],**settings) if __name__ == "__main__": application.listen(80) ioloop.IOLoop.instance().start()
account.py
from tornado import ioloop from tornado.web import RequestHandler,Application class LoginHandler(RequestHandler): def get(self,*args, **kwargs): self.render(\'login.html\',msg="") def post(self, *args, **kwargs): """ self.request 包含了所有数据: HTTPServerRequest(protocol=\'http\', host=\'127.0.0.1\', method=\'POST\', uri=\'/login.html?next=%2Fseed.html\', version=\'HTTP/1.1\', remote_ip=\'127.0.0.1\', headers={ \'Content-Type\': \'application/x-www-form-urlencoded\', \'Connection\': \'keep-alive\', \'Upgrade-Insecure-Requests\': \'1\', \'User-Agent\': \'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\', \'Cache-Control\': \'max-age=0\', \'Host\': \'127.0.0.1\', \'Accept-Encoding\': \'gzip, deflate, br\', \'Origin\': \'http://127.0.0.1\', \'Content-Length\': \'87\', \'Referer\': \'http://127.0.0.1/login.html?next=%2Fseed.html\', \'Accept-Language\': \'zh-CN,zh;q=0.9\', \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\', \'Cookie\': \'session=eyJ1c2VyX2luZm8iOiJhbGV4In0.DYUE4A.AhS8WvwJlQa8ium1YnF6tgJHwn0; _xsrf=2|50188c8e|5f181ad48a05219cb3bcf8117255223f|1520676667\' }) """ name = self.get_argument(\'name\') # 去GET和POST里取值 pwd = self.get_argument(\'pwd\') args = self.get_arguments(\'name\') # 类似Django里的 getlist() # self.get_query_argument() # 去GET里取值 # self.get_query_arguments() # 类似Django里的 getlist() # self.get_body_argument() # 去POST里取值 # self.get_body_arguments() # # 类似Django里的 getlist() if \'alex\' == name and \'123\' == pwd: import time deadline = time.time() + 3600 # self.set_cookie(\'user_info\',name,expires=deadline) # 普通的cookie self.set_secure_cookie(\'user_info\',name,expires=deadline) # 加盐/签名的cookie,需要在settings里配置cookie_secret # self.redirect(\'/seed.html\') # url = self.reverse_url(\'seed\') # self.redirect(url) # 如果使用authenticated来装饰login的get方法,并且在验证发现用户没有登录的情况下 # 则在跳转到登录页面,并会自动带上一个next字段到get请求里:http://127.0.0.1/login.html?next=%2Fseed.html next_url = self.get_query_argument(\'next\',\'\') if not next_url: next_url = self.reverse_url(\'seed\') self.redirect(next_url) else: self.render(\'login.html\',msg="用户名或密码错误") class LogoutHandler(RequestHandler): def get(self,*args, **kwargs): self.write("Bye...") def post(self, *args, **kwargs): pass
seed.py
from tornado import ioloop from tornado.web import RequestHandler,Application from tornado.web import authenticated # 手写实现登录验证 # class SeedHandler(RequestHandler): # def get(self,*args, **kwargs): # # name = self.get_cookie(\'user_info\') # name = self.get_secure_cookie(\'user_info\') # if not name: # self.redirect(\'/login.html\') # return # self.write("Seed!") """ 单继承 class ParentHandler(RequestHandler): # 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法 def get_current_user(self): return self.get_secure_cookie(\'user_info\') # 使用装饰器实现登录验证 class SeedHandler(ParentHandler): @authenticated def get(self,*args, **kwargs): seed_list = [ {\'title\':\'小麦\',\'price\':20}, {\'title\':\'水稻\',\'price\':50}, {\'title\':\'玉米\',\'price\':30} ] self.render(\'seed.html\',seed_list=seed_list) class VideoHandler(ParentHandler): @authenticated def get(self, *args, **kwargs): video_list = [ {\'title\': \'柯南\', \'price\': 220}, {\'title\': \'一人之下\', \'price\': 90}, {\'title\': \'虫师\', \'price\': 40} ] self.render(\'video.html\', video_list=video_list) """ """ 多继承 """ class ParentHandler(object): # 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法 def get_current_user(self): return self.get_secure_cookie(\'user_info\') # 使用装饰器实现登录验证 class SeedHandler(ParentHandler,RequestHandler): @authenticated def get(self,*args, **kwargs): seed_list = [ {\'title\':\'小麦\',\'price\':20}, {\'title\':\'水稻\',\'price\':50}, {\'title\':\'玉米\',\'price\':30} ] self.render(\'seed.html\',seed_list=seed_list) class VideoHandler(ParentHandler,RequestHandler): @authenticated def get(self, *args, **kwargs): video_list = [ {\'title\': \'柯南\', \'price\': 220}, {\'title\': \'一人之下\', \'price\': 90}, {\'title\': \'虫师\', \'price\': 40} ] self.render(\'video.html\', video_list=video_list)
自定义UIMethod以UIModule
def tab(self): """ 在html页面里的调用方式: {{ tab() }} {% raw tab() %} """ # print(self) # <controllers.seed.VideoHandler object at 0x000000000360D6A0> # return \'UIMethod\' return "<a href=\'http://www.baidu.com\'>百度</a>" def sum(self, num1, num2): return num1+num2
from tornado.web import UIModule from tornado import escape class Custom(UIModule): def render(self, *args, **kwargs): print(self,args,kwargs) return "UIModule 不仅可以返回内容还可以引入/嵌入 css和js,可以用来做一个自定制的组合模块,比如分页,只需要在使用的时候引入下就可以。" # 引入css def css_files(self): return ["/static/footer.css",] # 嵌入css def embedded_css(self): tpm = """ .foot{ height: 80px; } """ return tpm # 引入js def javascript_files(self): return ["/static/common.js",] # 嵌入js def embedded_javascript(self): tpm =""" v = 123; console.log(v); """ return tpm
seed.html
{% extends layout.html %} {% block content %} <h1>种子列表</h1> {% module Custom(123) %} <ul> {% for item in seed_list %} <li> {{ item[\'title\'] }} - {{ item[\'price\'] }}</li> <li> {{ item.get(\'title\',\'\') }} - {{ item.get(\'price\',\'\') }}</li> {% end %} </ul> {% include \'footer.html\' %} {% end %}
video.html
{% extends layout.html %} {% block content %} <h1>视频列表 {{ sum(1,3) }}</h1> {{ tab() }} {% raw tab() %} <ul> {% for item in video_list %} <li> {{ item[\'title\'] }} - {{ item[\'price\'] }}</li> <li> {{ item.get(\'title\',\'\') }} - {{ item.get(\'price\',\'\') }}</li> {% end %} </ul> {% end %}
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!--<link rel="stylesheet" href="/static/commons.css">--> <link rel="stylesheet" href="{{ static_url(\'commons.css\') }}"> </head> <body> <h1 class="c1">Login</h1> <form action="" method="post"> {% raw xsrf_form_html() %} <input type="text" name="name"> <input type="text" name="pwd"> <input type="submit" value="提交"> {{ msg }} </form> </body> </html>
更多请参考:http://www.cnblogs.com/wupeiqi/articles/5702910.html
以上是关于Tornado基本应用的主要内容,如果未能解决你的问题,请参考以下文章
tornado 启动WSGI应用(Flask)使用多线程将同步代码变成异步