Tornado简介

Tornado有自己的socket(异步非阻塞,原生支持WebSocket),Django没有。

Tornado的模板语言更接近Python风格,比Django要好理解。

Demo示例

  1. from tornado import ioloop
  2. from tornado.web import RequestHandler,Application
  3.  
  4. class IndexHandler(RequestHandler):
  5. def get(self):
  6. self.write("Hello, world")
  7.  
  8. application = Application([
  9. (r"/index", IndexHandler),
  10. ])
  11.  
  12. if __name__ == "__main__":
  13. application.listen(8888)
  14. ioloop.IOLoop.instance().start()

  

Tornado路由系统以及通过别名反向生成url

  1. from tornado import ioloop
  2. from tornado.web import RequestHandler,Application
  3.  
  4. class IndexHandler(RequestHandler):
  5. def get(self):
  6. url1 = self.application.reverse_url('alias_name1')
  7. url2 = self.application.reverse_url('alias_name2',666)
  8. print(url1)
  9. print(url2)
  10. self.write("Hello, world")
  11.  
  12. class HomeHandler(RequestHandler):
  13. def get(self,uid):
  14. print(uid)
  15. self.write("Hello, Home")
  16.  
  17. application = Application([
  18. (r"/index", IndexHandler,{},'alias_name1'),
  19. (r"/home/(\d+)", HomeHandler,{},'alias_name2'),
  20. ])
  21.  
  22. # 支持通过域名进行匹配,域名匹配到然后再匹配 url
  23. # application.add_handlers("blog.standby.pub",[
  24. # (r"/index", IndexHandler),
  25. # (r"/home/(\d+)", HomeHandler),
  26. # ])
  27.  
  28. if __name__ == "__main__":
  29. application.listen(80)
  30. ioloop.IOLoop.instance().start()

  

种子管理系统

  路由系统

  多种方式实现登录验证

  cookie

  xsrf

  UImethod 和 UImodule

  模板引擎

  

目录结构

  1. tree /f
  2.  
  3. app.py
  4. my_uimethod.py
  5. my_uimodule.py

  6. ├─controllers
  7. account.py
  8. seed.py
  9. __init__.py


  10. ├─statics
  11. commons.css
  12. footer.css

  13. ├─tpl
  14. footer.html
  15. layout.html
  16. login.html
  17. seed.html
  18. video.html

  

app.py

  1. from controllers.account import *
  2. from controllers.seed import *
  3. import my_uimethod
  4. import my_uimodule
  5.  
  6. settings = {
  7. 'template_path':'tpl',
  8. 'static_path':'statics',
  9. 'static_url_prefix':'/static/',
  10. 'xsrf_cookies': True, # csrf配置
  11. 'cookie_secret':'asahcaoclacnqwncakcnal',
  12. 'login_url':'/login.html',
  13. 'ui_methods':my_uimethod,
  14. 'ui_modules':my_uimodule,
  15. }
  16.  
  17. application = Application([
  18. (r"/login.html", LoginHandler,{},'login'),
  19. (r"/logout.html", LogoutHandler,{},'logout'),
  20. (r"/seed.html", SeedHandler,{},'seed'),
  21. (r"/video.html", VideoHandler,{},'video'),
  22. ],**settings)
  23.  
  24. if __name__ == "__main__":
  25. application.listen(80)
  26. ioloop.IOLoop.instance().start()

  

account.py

  1. from tornado import ioloop
  2. from tornado.web import RequestHandler,Application
  3.  
  4. class LoginHandler(RequestHandler):
  5. def get(self,*args, **kwargs):
  6. self.render('login.html',msg="")
  7.  
  8. def post(self, *args, **kwargs):
  9. """
  10. self.request 包含了所有数据:
  11. HTTPServerRequest(protocol='http',
  12. host='127.0.0.1',
  13. method='POST',
  14. uri='/login.html?next=%2Fseed.html',
  15. version='HTTP/1.1',
  16. remote_ip='127.0.0.1',
  17. headers={
  18. 'Content-Type': 'application/x-www-form-urlencoded',
  19. 'Connection': 'keep-alive',
  20. 'Upgrade-Insecure-Requests': '1',
  21. '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',
  22. 'Cache-Control': 'max-age=0',
  23. 'Host': '127.0.0.1',
  24. 'Accept-Encoding': 'gzip, deflate, br',
  25. 'Origin': 'http://127.0.0.1',
  26. 'Content-Length': '87',
  27. 'Referer': 'http://127.0.0.1/login.html?next=%2Fseed.html',
  28. 'Accept-Language': 'zh-CN,zh;q=0.9',
  29. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  30. 'Cookie': 'session=eyJ1c2VyX2luZm8iOiJhbGV4In0.DYUE4A.AhS8WvwJlQa8ium1YnF6tgJHwn0; _xsrf=2|50188c8e|5f181ad48a05219cb3bcf8117255223f|1520676667'
  31. })
  32. """
  33.  
  34. name = self.get_argument('name') # 去GET和POST里取值
  35. pwd = self.get_argument('pwd')
  36. args = self.get_arguments('name') # 类似Django里的 getlist()
  37. # self.get_query_argument() # 去GET里取值
  38. # self.get_query_arguments() # 类似Django里的 getlist()
  39. # self.get_body_argument() # 去POST里取值
  40. # self.get_body_arguments() # # 类似Django里的 getlist()
  41.  
  42. if 'alex' == name and '123' == pwd:
  43. import time
  44. deadline = time.time() + 3600
  45. # self.set_cookie('user_info',name,expires=deadline) # 普通的cookie
  46. self.set_secure_cookie('user_info',name,expires=deadline) # 加盐/签名的cookie,需要在settings里配置cookie_secret
  47.  
  48. # self.redirect('/seed.html')
  49. # url = self.reverse_url('seed')
  50. # self.redirect(url)
  51.  
  52. # 如果使用authenticated来装饰login的get方法,并且在验证发现用户没有登录的情况下
  53. # 则在跳转到登录页面,并会自动带上一个next字段到get请求里:http://127.0.0.1/login.html?next=%2Fseed.html
  54. next_url = self.get_query_argument('next','')
  55. if not next_url:
  56. next_url = self.reverse_url('seed')
  57. self.redirect(next_url)
  58. else:
  59. self.render('login.html',msg="用户名或密码错误")
  60.  
  61. class LogoutHandler(RequestHandler):
  62. def get(self,*args, **kwargs):
  63. self.write("Bye...")
  64. def post(self, *args, **kwargs):
  65. pass

  

seed.py

  1. from tornado import ioloop
  2. from tornado.web import RequestHandler,Application
  3. from tornado.web import authenticated
  4.  
  5. # 手写实现登录验证
  6. # class SeedHandler(RequestHandler):
  7. # def get(self,*args, **kwargs):
  8. # # name = self.get_cookie('user_info')
  9. # name = self.get_secure_cookie('user_info')
  10. # if not name:
  11. # self.redirect('/login.html')
  12. # return
  13. # self.write("Seed!")
  14.  
  15. """ 单继承
  16. class ParentHandler(RequestHandler):
  17. # 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法
  18. def get_current_user(self):
  19. return self.get_secure_cookie('user_info')
  20.  
  21. # 使用装饰器实现登录验证
  22. class SeedHandler(ParentHandler):
  23.  
  24. @authenticated
  25. def get(self,*args, **kwargs):
  26. seed_list = [
  27. {'title':'小麦','price':20},
  28. {'title':'水稻','price':50},
  29. {'title':'玉米','price':30}
  30. ]
  31. self.render('seed.html',seed_list=seed_list)
  32.  
  33. class VideoHandler(ParentHandler):
  34.  
  35. @authenticated
  36. def get(self, *args, **kwargs):
  37. video_list = [
  38. {'title': '柯南', 'price': 220},
  39. {'title': '一人之下', 'price': 90},
  40. {'title': '虫师', 'price': 40}
  41. ]
  42. self.render('video.html', video_list=video_list)
  43.  
  44. """
  45.  
  46. """ 多继承 """
  47. class ParentHandler(object):
  48. # 这个方法是tornado给预留的,如果要使用 tornado.web.authenticated 来登录验证就必须自己重写这个方法
  49. def get_current_user(self):
  50. return self.get_secure_cookie('user_info')
  51.  
  52. # 使用装饰器实现登录验证
  53. class SeedHandler(ParentHandler,RequestHandler):
  54.  
  55. @authenticated
  56. def get(self,*args, **kwargs):
  57. seed_list = [
  58. {'title':'小麦','price':20},
  59. {'title':'水稻','price':50},
  60. {'title':'玉米','price':30}
  61. ]
  62. self.render('seed.html',seed_list=seed_list)
  63.  
  64. class VideoHandler(ParentHandler,RequestHandler):
  65.  
  66. @authenticated
  67. def get(self, *args, **kwargs):
  68. video_list = [
  69. {'title': '柯南', 'price': 220},
  70. {'title': '一人之下', 'price': 90},
  71. {'title': '虫师', 'price': 40}
  72. ]
  73. self.render('video.html', video_list=video_list)

  

自定义UIMethod以UIModule

  1. def tab(self):
  2. """
  3. 在html页面里的调用方式:
  4. {{ tab() }}
  5. {% raw tab() %}
  6. """
  7. # print(self) # <controllers.seed.VideoHandler object at 0x000000000360D6A0>
  8. # return 'UIMethod'
  9. return "<a href='http://www.baidu.com'>百度</a>"
  10.  
  11. def sum(self, num1, num2):
  12. return num1+num2

  

  1. from tornado.web import UIModule
  2. from tornado import escape
  3.  
  4. class Custom(UIModule):
  5. def render(self, *args, **kwargs):
  6. print(self,args,kwargs)
  7. return "UIModule 不仅可以返回内容还可以引入/嵌入 css和js,可以用来做一个自定制的组合模块,比如分页,只需要在使用的时候引入下就可以。"
  8.  
  9. # 引入css
  10. def css_files(self):
  11. return ["/static/footer.css",]
  12.  
  13. # 嵌入css
  14. def embedded_css(self):
  15. tpm = """
  16. .foot{
  17. height: 80px;
  18. }
  19. """
  20. return tpm
  21.  
  22. # 引入js
  23. def javascript_files(self):
  24. return ["/static/common.js",]
  25.  
  26. # 嵌入js
  27. def embedded_javascript(self):
  28. tpm ="""
  29. v = 123;
  30. console.log(v);
  31. """
  32. return tpm

  

seed.html

  1. {% extends layout.html %}
  2.  
  3. {% block content %}
  4.  
  5. <h1>种子列表</h1>
  6.  
  7. {% module Custom(123) %}
  8.  
  9. <ul>
  10. {% for item in seed_list %}
  11. <li> {{ item['title'] }} - {{ item['price'] }}</li>
  12. <li> {{ item.get('title','') }} - {{ item.get('price','') }}</li>
  13. {% end %}
  14. </ul>
  15.  
  16. {% include 'footer.html' %}
  17. {% end %}

  

video.html

  1. {% extends layout.html %}
  2.  
  3. {% block content %}
  4.  
  5. <h1>视频列表 {{ sum(1,3) }}</h1>
  6. {{ tab() }}
  7. {% raw tab() %}
  8. <ul>
  9. {% for item in video_list %}
  10. <li> {{ item['title'] }} - {{ item['price'] }}</li>
  11. <li> {{ item.get('title','') }} - {{ item.get('price','') }}</li>
  12. {% end %}
  13. </ul>
  14.  
  15. {% end %}

  

login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <!--<link rel="stylesheet" href="/static/commons.css">-->
  7. <link rel="stylesheet" href="{{ static_url('commons.css') }}">
  8. </head>
  9. <body>
  10.  
  11. <h1 class="c1">Login</h1>
  12. <form action="" method="post">
  13. {% raw xsrf_form_html() %}
  14. <input type="text" name="name">
  15. <input type="text" name="pwd">
  16. <input type="submit" value="提交"> {{ msg }}
  17. </form>
  18.  
  19. </body>
  20. </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. zabbix 常用监控模板

    以下为常用的服务监控,可直接通过zabbix的导入功能导入,做基本修改就可以使用nginx监控模板 <?xml version="1.0" encoding="UT ...

  2. AGC030 简要题解

    A - Poisonous Cookies 题意 有\(A\)个能解毒的普通饼干,\(B\)个能解毒的美味饼干,\(C\)个有毒的美味饼干,求最多能吃多少个美味饼干,每次吃完有毒的饼干后要解毒后才能继 ...

  3. 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 ...

  4. NOIP2015斗地主(搜索+模拟+贪心)

    %%%Luan 题面就不说了,和斗地主一样,给一组牌,求最少打几次. 注意一点,数据随机,这样我们瞎搞一搞就可以过,虽然直接贪心可以证明是错的. 枚举方法,每次搜索按照(三顺子>二顺子>普 ...

  5. 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 由负数取模的性质 ...

  6. sscanf、sprintf、stringstream常见用法

    转载自:https://blog.csdn.net/jllongbell/article/details/79092891 前言: 以前没有接触过stringstream这个类的时候,常用的字符串和数 ...

  7. 编写高质量代码:改善Java程序的151个建议 --[65~78]

    编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...

  8. html 网页背景图片根据屏幕大小CSS自动缩放

    https://blog.csdn.net/coslay/article/details/47109281 腾讯微博和QQ空间的登录背景图片是根据访客的屏幕大小自动缩放的,但是好像是用JQuery代码 ...

  9. Linux 系统设置sh文件开机自启动

    工作中有一个linux下的服务需要启动,但是机器总是断电,导致需要反复启动,找了一下开机自启动的方法,解决了这个问题.Linux设置开机自启动非常简单,只要找到rc.local文件,将你需要自启动的文 ...

  10. Contest1585 - 2018-2019赛季多校联合新生训练赛第一场(部分题解)

    Contest1585 - 2018-2019赛季多校联合新生训练赛第一场 C 10187 查找特定的合数 D 10188 传话游戏 H 10192 扫雷游戏 C 传送门 题干: 题目描述 自然数中除 ...