Tornado是一个基于python的web框架,xxxxx

安装

python -m pip install tornado

第一个Tornado程序

安装完毕我们就可以新建一个app.py文件,放入下面的代码直接运行就可以了,然后在浏览器访问127.0.0.1:8888

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

tornado执行过程:

  • 第一步:执行脚本,监听 8888 端口
  • 第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index
  • 第三步:服务器接受请求,并交由对应的类处理该请求
  • 第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
  • 第五步:方法返回值的字符串内容发送浏览器

路由系统

路由系统执行过程是:

用户访问一个指定url(如:www.abc.org/index)   ---->  路由系统去匹配url找到Handler  ---->  Handler处理用户请求(get/post)

路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类。

顺带提一句,Tornado自己基于socket实现Web服务,Django等需要依赖其他的wsgi

  1. import tornado.web
  2.  
  3. settings = {
  4. 'template_path': 'views',
  5. 'static_path': 'static',
  6. }
  7.  
  8. class IndexHandler(tornado.web.RequestHandler):
  9. def get(self,page=None):
  10. pass
  11.  
  12. def post(self, *args, **kwargs):
  13. pass
  14.  
  15. application = tornado.web.Application([
  16. (r"/", IndexHandler),
  17. (r"/index/", IndexHandler),
  18. ], **settings)
  19.  
  20. if __name__ == "__main__":
  21. application.listen(8000)
  22. tornado.ioloop.IOLoop.instance().start()

Tornado中原生支持二级域名的路由,如:

模板引擎

Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。

Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}

控制语句和对应的 Python 语句的格式基本完全相同。我们支持 ifforwhile 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述。

在模板中默认提供了一些函数、字段、类以供模板使用:

  1. escape: tornado.escape.xhtml_escape 的別名
  2. xhtml_escape: tornado.escape.xhtml_escape 的別名
  3. url_escape: tornado.escape.url_escape 的別名
  4. json_encode: tornado.escape.json_encode 的別名
  5. squeeze: tornado.escape.squeeze 的別名
  6. linkify: tornado.escape.linkify 的別名
  7. datetime: Python datetime 模组
  8. handler: 当前的 RequestHandler 对象
  9. request: handler.request 的別名
  10. current_user: handler.current_user 的別名
  11. locale: handler.locale 的別名
  12. _: handler.locale.translate 的別名
  13. static_url: for handler.static_url 的別名
  14. xsrf_form_html: handler.xsrf_form_html 的別名

Tornado默认提供的这些功能其实本质上就是 UIMethod 和 UIModule,我们也可以自定义从而实现类似于Django的simple_tag的功能:

母板

1.定义

母板完整代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>抽屉新热榜-聚合每日热门、搞笑、有趣资讯</title>
  6. <link type="text/css" rel="stylesheet" href="{{ static_url('css/common.css') }}" />
  7. <!--<link rel="stylesheet" href='{{static_url("plugins/bootstrap3/css/bootstrap.css") }}' />-->
  8. </head>
  9. <body>
  10. <div class="top">
  11. <div class="top-content">
  12. <img class="logo" src="/static/pic/logo.png">
  13. <div class="action-menu">
  14. <ul class="nav-ul">
  15. <li class="nav-li"><a href="/">全部</a></li>
  16. <li class="nav-li"><a>42区</a></li>
  17. <li class="nav-li"><a>段子</a></li>
  18. <li class="nav-li"><a>图片</a></li>
  19. <li class="nav-li"><a>挨踢1024</a></li>
  20. <li class="nav-li"><a>你问我答</a></li>
  21. </ul>
  22. </div>
  23. <div class="search-ground">
  24. <span class="search-ico"></span>
  25. </div>
  26. <div>
  27. <form action="https://www.sogou.com/qurey" name="qurey" method="get">
  28. <input type="text" class="search-box">
  29. </form>
  30. </div>
  31. <div>
  32. {% if user_info["is_login"] %}
  33. <div class="nav-2">
  34. <a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
  35. <img src="http://img2.chouti.com/CHOUTI_05B313F703D34646848BCC5571510683_W148H148=30x30).jpg" id="userProImg">
  36. <span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
  37. <em id="userProArr"></em>
  38. </a>
  39. <div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
  40. </div>
  41. {% else %}
  42. <div class="nav-2"><a href="/login">登录</a></div>
  43. <div class="nav-2"><a href="/reg">注册</a></div>
  44. {% end %}
  45. </div>
  46.  
  47. </div>
  48. </div>
  49. <div class="background">
  50. <div class="main-content">
  51. {% block middle %}{% end %}
  52. <div class="footer">
  53. <div class="footer-item">
  54. <hr>
  55. <a >关于我们</a>
  56. <span>|</span>
  57. <a>联系我们</a>
  58. <span>|</span>
  59. <a>服务条款</a>
  60. <span>|</span>
  61. <a>隐私政策</a>
  62. <span>|</span>
  63. <a>抽屉新热榜工具</a>
  64. <span>|</span>
  65. <a>下载客户端</a>
  66. <span>|</span>
  67. <a>意见与反馈</a>
  68. <span>|</span>
  69. <a>友情链接</a>
  70. <span>|</span>
  71. <a>公告</a>
  72. <span>|</span>
  73. <img src="http://dig.chouti.com/images/ct_rss.gif">
  74. </div>
  75. <div class="footer-item2">
  76. <a target="_blank" href="http://www.gozap.com/"><img class="foot_e" src="http://dig.chouti.com/images/gozap-logo-50_15.gif"></a>
  77. <span class="foot_d">旗下站点</span>
  78. <span class="foot_a">&copy; 2016 chouti.com</span>
  79. <a target="_blank" href="http://www.miibeian.gov.cn/" class="foot_b">京ICP备09053974号-3 京公网安备 110102004562</a>
  80. <div style="margin-top:6px; text-align: center">版权所有:北京格致璞科技有限公司</div>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. </body>
  86. </html>

2.使用

子板完整代码

  1. {% extends '../master/layout.html' %}
  2.  
  3. {% block middle %}
  4. <div class="left">
  5. <div class="nav-top-area">
  6. <div class="child-nav">
  7. <div class="hotbtn">
  8. <a href="/all/hot/recent/1" hidefocus="false" >最热</a>
  9. </div>
  10. <div class="newbtn">
  11. <a href="/all/new/1" hidefocus="false" >最新</a>
  12. </div>
  13. <div class="personbtn">
  14. <a href="/all/man/1" hidefocus="false" >人类发布</a>
  15. </div>
  16. </div>
  17.  
  18. <div href="javascript:;" class="publish-btn">
  19. <!--<a class="ico n1"></a><a class="n2">发布</a>-->
  20. <a class="publish-icon" href="/publish">发布</a>
  21. </div>
  22.  
  23. <div class="sort-nav">
  24. <a href="/all/hot/recent/1" hidefocus="false" class="active hotbtn" style="color: #b4b4b4;">即时排序</a>
  25. <a href="/all/hot/24hr/1" hidefocus="false" class="newbtn" style="color: #390;;">24小时</a>
  26. <a href="/all/hot/72hr/1" hidefocus="false" class="newbtn" style="color: #390;;">3天</a>
  27. </div>
  28. </div>
  29. <div class="content-list">
  30. {% for new in news_list %}
  31. <div class="item">
  32. <div class="news-pic">
  33. <img src="{{new['post_img']}}">
  34. </div>
  35. <div class="part1">
  36. <a>{{new['post_title']}}</a>
  37. <span>douban.com</span>
  38. <span>42区</span>
  39. </div>
  40. <div class="part2">
  41. <span>{{new['post_content']}}</span>
  42. </div>
  43. </div>
  44. {% end %}
  45. </div>
  46. <div class="pager">
  47. <!--阻止转义-->
  48. {% raw str_page %}
  49. </div>
  50. </div>
  51. <div class="right">
  52. <div class="chat-area">
  53. <img src="/static/pic/chouti-chat.png">
  54. </div>
  55. <div style="height: 581px; width: 312px; margin-top: 20px; margin-bottom: 20px;">
  56. <img src="/static/pic/top24.png">
  57. </div>
  58. <div style="height: 200px; width: 300px">
  59. <img src="/static/pic/ad_c155.jpg">
  60. </div>
  61. </div>
  62. {% end %}

3.include

include可以吧常用的小部件如登录框写在一个html文件里

让其他页面直接调用,提高代码的复用性

一个网页既调用母板 内部内容直接调用include的例子:

  1. {% extends '../master/layout.html' %}
  2. {% block middle %}
  3. {% include '../include/login.html' %}
  4. {% end %}

4.模板语言里的if判断和for循环

for循环

对于Handler里面post或者get方法里面render时候传入一个news_list的字典

模板语言循环解析他

例子:

  1. <div class="content-list">
  2. {% for new in news_list %}
  3. <div class="item">
  4. <div class="news-pic">
  5. <img src="{{new['post_img']}}">
  6. </div>
  7. <div class="part1">
  8. <a>{{new['post_title']}}</a>
  9. <span>douban.com</span>
  10. <span>42区</span>
  11. </div>
  12. <div class="part2">
  13. <span>{{new['post_content']}}</span>
  14. </div>
  15. </div>
  16. {% end %}
  17. </div>

if判断

可以根据接收到的判断显示还是不显示某个html代码块

例子:

  1. <div>
  2. {% if user_info["is_login"] %}
  3. <div class="nav-2">
  4. <a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
  5. <img src="http://img2.chouti.com/CHOUTI_05B3131510683_W148H148=30x30).jpg" id="userProImg">
  6. <span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
  7. <em id="userProArr"></em>
  8. </a>
  9. <div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
  10. </div>
  11. {% else %}
  12. <div class="nav-2"><a href="/login">登录</a></div>
  13. <div class="nav-2"><a href="/reg">注册</a></div>
  14. {% end %}
  15. </div>

自定义UIMethod以UIModule

a.定义

  1. # uimethods.py
  2.  
  3. def tab(self):
  4. return 'UIMethod'

uimethods.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from tornado.web import UIModule
  4. from tornado import escape
  5.  
  6. class custom(UIModule):
  7.  
  8. def render(self, *args, **kwargs):
  9. return escape.xhtml_escape('<h1>wupeiqi</h1>')
  10. #return escape.xhtml_escape('<h1>wupeiqi</h1>')
  11.  
  12. uimodules.py

uimodules.py

b.注册

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. #!/usr/bin/env python
  4. # -*- coding:utf-8 -*-
  5.  
  6. import tornado.ioloop
  7. import tornado.web
  8. from tornado.escape import linkify
  9. import uimodules as md
  10. import uimethods as mt
  11.  
  12. class MainHandler(tornado.web.RequestHandler):
  13. def get(self):
  14. self.render('index.html')
  15.  
  16. settings = {
  17. 'template_path': 'template',
  18. 'static_path': 'static',
  19. 'static_url_prefix': '/static/',
  20. 'ui_methods': mt,
  21. 'ui_modules': md,
  22. }
  23.  
  24. application = tornado.web.Application([
  25. (r"/index", MainHandler),
  26. ], **settings)
  27.  
  28. if __name__ == "__main__":
  29. application.listen(8009)
  30. tornado.ioloop.IOLoop.instance().start()

c.使用

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <link href="{{static_url("commons.css")}}" rel="stylesheet" />
  7. </head>
  8. <body>
  9. <h1>hello</h1>
  10. {% module custom(123) %}
  11. {{ tab() }}
  12. </body>

附:一个比较规范的Tornado project layout

有关cookie,session,验证码,表单验证,csrf,xss,ajax我们将在下一篇博文里面继续探讨

[Python笔记]第十六篇:web框架之Tornado的更多相关文章

  1. 【Python之路】第十六篇--Web框架之Tornado

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

  2. python笔记-19 javascript补充、web框架、django基础

    一.JavaScript的补充 1 正则表达式 1.1 test的使用 test 测试是否符合条件 返回true or false 1.2 exec的使用 exec 从字符串中截取匹配的字符 1.3 ...

  3. 【Python之路】第十五篇--Web框架

    Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf- ...

  4. Python 学习 第十六篇:networkx

    networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法.图是由顶点.边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系.顶点和边 ...

  5. Python学习第十六篇——异常处理

    在实际中,很多时候时候,我们并不能保证我们所写的程序是完美的.比如我们程序的本意是:用户在输入框内输入数字,并进行后续数学运算,即使我们提醒了用户需要输入数字而不是文本,但是有时会无意或者恶意输入字符 ...

  6. Python笔记(二十六)_魔法方法_属性的魔法方法

    属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...

  7. python【第十六篇】DOM

    文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口. DOM可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构.换句 ...

  8. Python笔记(十六):迭代器

    (一)iterable对象和Iterator对象的区别 iterable对象(可迭代的对象):可以使用for循环,例如:字符串.列表 .字典 .集合等 Iterator对象(迭代器):除了可以用for ...

  9. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

随机推荐

  1. CAS+SSO原理浅谈

    http://www.cnblogs.com/yonsin/archive/2009/08/29/1556423.htmlSSO 是一个非常大的主题,我对这个主题有着深深的感受,自从广州 UserGr ...

  2. JAVA中list,set,数组之间的转换详解

    JAVA的list,set,数组之间的转换,主要是使用Apache Jakarta Commons Collections,具体的方法如下:import org.apache.commons.coll ...

  3. 解决Qt5使用SSL的“qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method”错误

    在使用Qt的网络组件连接某些服务器时, 会提示"qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method"的错误 ...

  4. ASP.NET多线程下使用HttpContext.Current为null解决方案

    多线程或者异步调用中如何访问HttpContext? 前面我还提到在APM模式下的异步完成回调时,访问HttpContext.Current也会返回null,那么此时该怎么办呢? 答案有二种:1. 在 ...

  5. 【转】java.lang.StackOverflowError

    http://blog.csdn.net/g19920917/article/details/8765638 出现一个java.lang.StackOverflowError异常.弄了半天,又是问高手 ...

  6. MVC Controller return 格式

    所看到的Action都是return View();我们可以看作这个返回值用于解析一个aspx文件.而它的返回类型是ActionResult如 public ActionResult Index()  ...

  7. ContentProvider与ContentResolver使用

    例如以下内容为从网络转载: 使用ContentProvider共享数据: 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就能够向其它应用共享其数据.虽然使用其它方 ...

  8. Openstack Ice-House 版本号说明--之中的一个 NOVA

    OpenStack Icehouse在4.17正式公布,看了下release note,发现改变不小,说明openstack还是在高速发展中,有不少新的特性增加,也有些小的剔除.以下就我所关注的项目做 ...

  9. myeclipse2014新感悟

    部署有两种方式:1.直接把文件拷贝到 tomcat下的webroot文件夹下 2.myeclipse软件内部点击“deploy”部署 →点击add→tomcat下的webroot文件夹下 点击完“运行 ...

  10. java Map使用Object 做为Key的问题

    近期在看dnsjava 源码的时候,不经意间发现一个自己没有想过的问题: HashMap 如何使用key去查找对应的value的,这个问题很难用语言描述的清楚,那就使用代码来进行说明吧! public ...