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基本应用的更多相关文章
- Python(九)Tornado web 框架
一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...
- 使用tornado,我们可以做什么?
以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可. 如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用t ...
- tornado session
[转]tornado入门 - session cookie 和session 的区别: 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以 ...
- tornado template
若果使用Tornado进行web开发可能会用到模板功能,页面继承,嵌套... 多页应用模板的处理多半依赖后端(SPA就可以动态加载局部视图),就算是RESTfull的API设计,也不妨碍同时提供部分模 ...
- tornado上手
http://www.tornadoweb.org/en/stable/ http://www.cnblogs.com/fanweibin/p/5418697.html import tornado. ...
- tornado+sqlalchemy+celery,数据库连接消耗在哪里
随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知. 最近老是发现数据库的连接数如果 ...
- centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)
首先,本来不想写这篇博客了,但是我测试了很多网上的例子包括简书的,全不行,我总结原因是自己太笨,搞了俩个晚上,后来决定,自己还是写一篇记录下来,保证自己以后使用 环境: centos6.7 64 py ...
- tornado中将cookie值设置为json字符串
不熟悉,找了很久,能FQ的话, https://groups.google.com/forum/#!topic/python-tornado/9Y--NgwjP_w 2楼有解释. tornado.es ...
- tornado 异步调用系统命令和非阻塞线程池
项目中异步调用 ping 和 nmap 实现对目标 ip 和所在网关的探测 Subprocess.STREAM 不用担心进程返回数据过大造成的死锁, Subprocess.PIPE 会有这个问题. i ...
- 离线安装 Python 2.7, paramiko 和 tornado
无非就是离线安装, 步骤比较繁琐, 记录一下. 需求很简单, 一个离线安装的 Python, 能跑 tornado 和 paramiko 1. 离线安装 Python 2.7 .tgz cd Pyth ...
随机推荐
- zabbix 常用监控模板
以下为常用的服务监控,可直接通过zabbix的导入功能导入,做基本修改就可以使用nginx监控模板 <?xml version="1.0" encoding="UT ...
- AGC030 简要题解
A - Poisonous Cookies 题意 有\(A\)个能解毒的普通饼干,\(B\)个能解毒的美味饼干,\(C\)个有毒的美味饼干,求最多能吃多少个美味饼干,每次吃完有毒的饼干后要解毒后才能继 ...
- Android 错误提示: Can't create handler inside thread that has not called Looper.prepare()
Can't create handler inside thread that has not called Looper.prepare() 将 Handler handler = new Hand ...
- NOIP2015斗地主(搜索+模拟+贪心)
%%%Luan 题面就不说了,和斗地主一样,给一组牌,求最少打几次. 注意一点,数据随机,这样我们瞎搞一搞就可以过,虽然直接贪心可以证明是错的. 枚举方法,每次搜索按照(三顺子>二顺子>普 ...
- 2018 ICPC 焦作网络赛 E.Jiu Yuan Wants to Eat
题意:四个操作,区间加,区间每个数乘,区间的数变成 2^64-1-x,求区间和. 题解:2^64-1-x=(2^64-1)-x 因为模数为2^64,-x%2^64=-1*x%2^64 由负数取模的性质 ...
- sscanf、sprintf、stringstream常见用法
转载自:https://blog.csdn.net/jllongbell/article/details/79092891 前言: 以前没有接触过stringstream这个类的时候,常用的字符串和数 ...
- 编写高质量代码:改善Java程序的151个建议 --[65~78]
编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...
- html 网页背景图片根据屏幕大小CSS自动缩放
https://blog.csdn.net/coslay/article/details/47109281 腾讯微博和QQ空间的登录背景图片是根据访客的屏幕大小自动缩放的,但是好像是用JQuery代码 ...
- Linux 系统设置sh文件开机自启动
工作中有一个linux下的服务需要启动,但是机器总是断电,导致需要反复启动,找了一下开机自启动的方法,解决了这个问题.Linux设置开机自启动非常简单,只要找到rc.local文件,将你需要自启动的文 ...
- Contest1585 - 2018-2019赛季多校联合新生训练赛第一场(部分题解)
Contest1585 - 2018-2019赛季多校联合新生训练赛第一场 C 10187 查找特定的合数 D 10188 传话游戏 H 10192 扫雷游戏 C 传送门 题干: 题目描述 自然数中除 ...