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基本应用的更多相关文章

  1. Python(九)Tornado web 框架

    一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...

  2. 使用tornado,我们可以做什么?

    以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可. 如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用t ...

  3. tornado session

    [转]tornado入门 - session cookie 和session 的区别: 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以 ...

  4. tornado template

    若果使用Tornado进行web开发可能会用到模板功能,页面继承,嵌套... 多页应用模板的处理多半依赖后端(SPA就可以动态加载局部视图),就算是RESTfull的API设计,也不妨碍同时提供部分模 ...

  5. tornado上手

    http://www.tornadoweb.org/en/stable/ http://www.cnblogs.com/fanweibin/p/5418697.html import tornado. ...

  6. tornado+sqlalchemy+celery,数据库连接消耗在哪里

    随着公司业务的发展,网站的日活数也逐渐增多,以前只需要考虑将所需要的功能实现就行了,当日活越来越大的时候,就需要考虑对服务器的资源使用消耗情况有一个清楚的认知.     最近老是发现数据库的连接数如果 ...

  7. centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)

    首先,本来不想写这篇博客了,但是我测试了很多网上的例子包括简书的,全不行,我总结原因是自己太笨,搞了俩个晚上,后来决定,自己还是写一篇记录下来,保证自己以后使用 环境: centos6.7 64 py ...

  8. tornado中将cookie值设置为json字符串

    不熟悉,找了很久,能FQ的话, https://groups.google.com/forum/#!topic/python-tornado/9Y--NgwjP_w 2楼有解释. tornado.es ...

  9. tornado 异步调用系统命令和非阻塞线程池

    项目中异步调用 ping 和 nmap 实现对目标 ip 和所在网关的探测 Subprocess.STREAM 不用担心进程返回数据过大造成的死锁, Subprocess.PIPE 会有这个问题. i ...

  10. 离线安装 Python 2.7, paramiko 和 tornado

    无非就是离线安装, 步骤比较繁琐, 记录一下. 需求很简单, 一个离线安装的 Python, 能跑 tornado 和 paramiko 1. 离线安装 Python 2.7 .tgz cd Pyth ...

随机推荐

  1. 【题解】 bzoj3555: [Ctsc2014]企鹅QQ (字符串Hash)

    题面戳我 Solution 我们分析题意,他要求的是两个字符串只有一个字符不同,然后我们再看长度\(L \leq 200\),显然我们就可以把每一位删除后\(Hash\),然后判断相同个数即可 我一开 ...

  2. SCOI2016 Day1 简要题解

    目录 「SCOI2016」背单词 题意 题解 代码 「SCOI2016」幸运数字 题意 题解 总结 代码 「SCOI2016」萌萌哒 题意 题解 总结 代码 「SCOI2016」背单词 题意 这出题人 ...

  3. 15 Zabbix Item类型之Zabbix trapper类型

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 15 Zabbix Item类型之Zabbix trapper类型 zabbix获取数据时有时会出 ...

  4. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  5. DP题组

    按照顺序来. Median Sum 大意: 给你一个集合,求其所有非空子集的权值的中位数. 某集合的权值即为其元素之和. 1 <= n <= 2000 解: 集合配对,每个集合都配对它的补 ...

  6. 【洛谷P1903】数颜色

    题目大意:给定一个长度为 N 的序列,每个点有一个颜色.现给出 M 个操作,支持单点修改颜色和询问区间颜色数两个操作. 题解:学会了序列带修改的莫队. 莫队本身是不支持修改的.带修该莫队的本质也是对询 ...

  7. Windows 查看端口占用情况

    今天打算运行一下当年的毕业设计,结果启动ActiveMQ的时候,发现报错 原来是端口占用了.在Windows上怎样看呢? Ctrl+Alt+Del 调出任务管理器 再找到资源监视器 原来是依赖于Erl ...

  8. HDU 1880 魔咒词典 (Hash)

    魔咒词典 Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. 利用sys打印进度条

    在很多常见中,需要对当前处理的进度进行显示,这个时候就需要进度条了,在python中,也有封装好的进度条模块,当然,也可以自己编写一个简单的进度条来帮助理解进度条的实现. 首先,需要理解一个概念,就是 ...

  10. Constructor >> @Autowired >> @PostConstruct

    从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入.所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发 ...