[Python笔记]第十六篇:web框架之Tornado
Tornado是一个基于python的web框架,xxxxx
安装
python -m pip install tornado
第一个Tornado程序
安装完毕我们就可以新建一个app.py文件,放入下面的代码直接运行就可以了,然后在浏览器访问127.0.0.1:8888
import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") application = tornado.web.Application([
(r"/", MainHandler),
]) if __name__ == "__main__":
application.listen(8888)
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
import tornado.web
settings = {
'template_path': 'views',
'static_path': 'static',
}
class IndexHandler(tornado.web.RequestHandler):
def get(self,page=None):
pass
def post(self, *args, **kwargs):
pass
application = tornado.web.Application([
(r"/", IndexHandler),
(r"/index/", IndexHandler),
], **settings)
if __name__ == "__main__":
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
Tornado中原生支持二级域名的路由,如:

模板引擎
Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。
Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}。
控制语句和对应的 Python 语句的格式基本完全相同。我们支持 if、for、while 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述。
在模板中默认提供了一些函数、字段、类以供模板使用:
escape: tornado.escape.xhtml_escape 的別名
xhtml_escape: tornado.escape.xhtml_escape 的別名
url_escape: tornado.escape.url_escape 的別名
json_encode: tornado.escape.json_encode 的別名
squeeze: tornado.escape.squeeze 的別名
linkify: tornado.escape.linkify 的別名
datetime: Python 的 datetime 模组
handler: 当前的 RequestHandler 对象
request: handler.request 的別名
current_user: handler.current_user 的別名
locale: handler.locale 的別名
_: handler.locale.translate 的別名
static_url: for handler.static_url 的別名
xsrf_form_html: handler.xsrf_form_html 的別名
Tornado默认提供的这些功能其实本质上就是 UIMethod 和 UIModule,我们也可以自定义从而实现类似于Django的simple_tag的功能:
母板
1.定义

母板完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>抽屉新热榜-聚合每日热门、搞笑、有趣资讯</title>
<link type="text/css" rel="stylesheet" href="{{ static_url('css/common.css') }}" />
<!--<link rel="stylesheet" href='{{static_url("plugins/bootstrap3/css/bootstrap.css") }}' />-->
</head>
<body>
<div class="top">
<div class="top-content">
<img class="logo" src="/static/pic/logo.png">
<div class="action-menu">
<ul class="nav-ul">
<li class="nav-li"><a href="/">全部</a></li>
<li class="nav-li"><a>42区</a></li>
<li class="nav-li"><a>段子</a></li>
<li class="nav-li"><a>图片</a></li>
<li class="nav-li"><a>挨踢1024</a></li>
<li class="nav-li"><a>你问我答</a></li>
</ul>
</div>
<div class="search-ground">
<span class="search-ico"></span>
</div>
<div>
<form action="https://www.sogou.com/qurey" name="qurey" method="get">
<input type="text" class="search-box">
</form>
</div>
<div>
{% if user_info["is_login"] %}
<div class="nav-2">
<a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
<img src="http://img2.chouti.com/CHOUTI_05B313F703D34646848BCC5571510683_W148H148=30x30).jpg" id="userProImg">
<span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
<em id="userProArr"></em>
</a>
<div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
</div>
{% else %}
<div class="nav-2"><a href="/login">登录</a></div>
<div class="nav-2"><a href="/reg">注册</a></div>
{% end %}
</div> </div>
</div>
<div class="background">
<div class="main-content">
{% block middle %}{% end %}
<div class="footer">
<div class="footer-item">
<hr>
<a >关于我们</a>
<span>|</span>
<a>联系我们</a>
<span>|</span>
<a>服务条款</a>
<span>|</span>
<a>隐私政策</a>
<span>|</span>
<a>抽屉新热榜工具</a>
<span>|</span>
<a>下载客户端</a>
<span>|</span>
<a>意见与反馈</a>
<span>|</span>
<a>友情链接</a>
<span>|</span>
<a>公告</a>
<span>|</span>
<img src="http://dig.chouti.com/images/ct_rss.gif">
</div>
<div class="footer-item2">
<a target="_blank" href="http://www.gozap.com/"><img class="foot_e" src="http://dig.chouti.com/images/gozap-logo-50_15.gif"></a>
<span class="foot_d">旗下站点</span>
<span class="foot_a">© 2016 chouti.com</span>
<a target="_blank" href="http://www.miibeian.gov.cn/" class="foot_b">京ICP备09053974号-3 京公网安备 110102004562</a>
<div style="margin-top:6px; text-align: center">版权所有:北京格致璞科技有限公司</div>
</div>
</div>
</div>
</div>
</body>
</html>
2.使用
子板完整代码
{% extends '../master/layout.html' %}
{% block middle %}
<div class="left">
<div class="nav-top-area">
<div class="child-nav">
<div class="hotbtn">
<a href="/all/hot/recent/1" hidefocus="false" >最热</a>
</div>
<div class="newbtn">
<a href="/all/new/1" hidefocus="false" >最新</a>
</div>
<div class="personbtn">
<a href="/all/man/1" hidefocus="false" >人类发布</a>
</div>
</div>
<div href="javascript:;" class="publish-btn">
<!--<a class="ico n1"></a><a class="n2">发布</a>-->
<a class="publish-icon" href="/publish">发布</a>
</div>
<div class="sort-nav">
<a href="/all/hot/recent/1" hidefocus="false" class="active hotbtn" style="color: #b4b4b4;">即时排序</a>
<a href="/all/hot/24hr/1" hidefocus="false" class="newbtn" style="color: #390;;">24小时</a>
<a href="/all/hot/72hr/1" hidefocus="false" class="newbtn" style="color: #390;;">3天</a>
</div>
</div>
<div class="content-list">
{% for new in news_list %}
<div class="item">
<div class="news-pic">
<img src="{{new['post_img']}}">
</div>
<div class="part1">
<a>{{new['post_title']}}</a>
<span>douban.com</span>
<span>42区</span>
</div>
<div class="part2">
<span>{{new['post_content']}}</span>
</div>
</div>
{% end %}
</div>
<div class="pager">
<!--阻止转义-->
{% raw str_page %}
</div>
</div>
<div class="right">
<div class="chat-area">
<img src="/static/pic/chouti-chat.png">
</div>
<div style="height: 581px; width: 312px; margin-top: 20px; margin-bottom: 20px;">
<img src="/static/pic/top24.png">
</div>
<div style="height: 200px; width: 300px">
<img src="/static/pic/ad_c155.jpg">
</div>
</div>
{% end %}
3.include
include可以吧常用的小部件如登录框写在一个html文件里
让其他页面直接调用,提高代码的复用性
一个网页既调用母板 内部内容直接调用include的例子:
{% extends '../master/layout.html' %}
{% block middle %}
{% include '../include/login.html' %}
{% end %}
4.模板语言里的if判断和for循环
for循环
对于Handler里面post或者get方法里面render时候传入一个news_list的字典
模板语言循环解析他
例子:
<div class="content-list">
{% for new in news_list %}
<div class="item">
<div class="news-pic">
<img src="{{new['post_img']}}">
</div>
<div class="part1">
<a>{{new['post_title']}}</a>
<span>douban.com</span>
<span>42区</span>
</div>
<div class="part2">
<span>{{new['post_content']}}</span>
</div>
</div>
{% end %}
</div>
if判断
可以根据接收到的判断显示还是不显示某个html代码块
例子:
<div>
{% if user_info["is_login"] %}
<div class="nav-2">
<a style="text-decoration: none;color: white" href="/user/link/saved/1" id="loginUserNc" class="userPro-Box" style="color: white">
<img src="http://img2.chouti.com/CHOUTI_05B3131510683_W148H148=30x30).jpg" id="userProImg">
<span class="u-nick" id="userProNick">{{user_info["username"]}}</span>
<em id="userProArr"></em>
</a>
<div class="nav-2"><a style="color: #d9edf7" href="/logout">退出</a></div>
</div>
{% else %}
<div class="nav-2"><a href="/login">登录</a></div>
<div class="nav-2"><a href="/reg">注册</a></div>
{% end %}
</div>
自定义UIMethod以UIModule
a.定义
# uimethods.py def tab(self):
return 'UIMethod'
uimethods.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from tornado.web import UIModule
from tornado import escape class custom(UIModule): def render(self, *args, **kwargs):
return escape.xhtml_escape('<h1>wupeiqi</h1>')
#return escape.xhtml_escape('<h1>wupeiqi</h1>') uimodules.py
uimodules.py
b.注册
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from tornado.escape import linkify
import uimodules as md
import uimethods as mt class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html') settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'ui_methods': mt,
'ui_modules': md,
} application = tornado.web.Application([
(r"/index", MainHandler),
], **settings) if __name__ == "__main__":
application.listen(8009)
tornado.ioloop.IOLoop.instance().start()
c.使用
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>hello</h1>
{% module custom(123) %}
{{ tab() }}
</body>
附:一个比较规范的Tornado project layout

有关cookie,session,验证码,表单验证,csrf,xss,ajax我们将在下一篇博文里面继续探讨
[Python笔记]第十六篇:web框架之Tornado的更多相关文章
- 【Python之路】第十六篇--Web框架之Tornado
概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...
- python笔记-19 javascript补充、web框架、django基础
一.JavaScript的补充 1 正则表达式 1.1 test的使用 test 测试是否符合条件 返回true or false 1.2 exec的使用 exec 从字符串中截取匹配的字符 1.3 ...
- 【Python之路】第十五篇--Web框架
Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf- ...
- Python 学习 第十六篇:networkx
networkx是Python的一个包,用于构建和操作复杂的图结构,提供分析图的算法.图是由顶点.边和可选的属性构成的数据结构,顶点表示数据,边是由两个顶点唯一确定的,表示两个顶点之间的关系.顶点和边 ...
- Python学习第十六篇——异常处理
在实际中,很多时候时候,我们并不能保证我们所写的程序是完美的.比如我们程序的本意是:用户在输入框内输入数字,并进行后续数学运算,即使我们提醒了用户需要输入数字而不是文本,但是有时会无意或者恶意输入字符 ...
- Python笔记(二十六)_魔法方法_属性的魔法方法
属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...
- python【第十六篇】DOM
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口. DOM可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构.换句 ...
- Python笔记(十六):迭代器
(一)iterable对象和Iterator对象的区别 iterable对象(可迭代的对象):可以使用for循环,例如:字符串.列表 .字典 .集合等 Iterator对象(迭代器):除了可以用for ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
随机推荐
- 关键字instanceof和final
Instanceof关键字(类似oc的isKindOfClass 和 isMemberOfClass) instanceof(实例类型) 关键字作用: 1.判断某一个对象是否属于某一个类 2.inst ...
- Sublime ctags 函数跳转插件安装
Sublime Text安装插件的方法,主要有以下两种: 1. 直接通过下载安装包安装 在编辑器菜单中点击“Preferences”–“Browse Packages…”打开插件安装目录,然后把下载的 ...
- Hibernate查询方法总结
1. HQL查询 HQL是Hiberante官方推荐的Hibernate检索方式,它使用类似SQL的查询语言,以面向对象的方式从数据库中查询.可以使用HQL查询具有继承.多态和关 联关系的数据.在检索 ...
- git与svn的区别-小结一下
1)Git是分布式的,SVN不是: 这 是GIT和其它非分布式的版本控制系 统,例如SVN,CVS等,最核心的区别.好处是跟其他同事不会有太多的冲突,自己写的代码放在自己电脑上,一段时间后再提交.合并 ...
- 三种排序算法python源码——冒泡排序、插入排序、选择排序
最近在学习python,用python实现几个简单的排序算法,一方面巩固一下数据结构的知识,另一方面加深一下python的简单语法. 冒泡排序算法的思路是对任意两个相邻的数据进行比较,每次将最小和最大 ...
- 格式化日期时间字符串 Get-Date -Uformat , -format
#将字符串格式化为时间格式 $dateTimeStr = '20141231T23:59:59' $format = 'yyyyMMddTHH:mm:ss' $formatProvider = [Gl ...
- 再谈内存管理与ARC运行机制(一)
内存管理 内存在Objective-C开发中是一种相对稀缺的资源,拿Iphone4为例,它的内存只有512mb,所以妥善的处理好所创造,所使用的每个对象与变量都将成为一个问题.在ARC出现以前,同大部 ...
- android 嵌套 apk 从一个apk启动另外一个apk
a.apk-主应用 b.apk-被启动应用 主要思想:把b.apk放到assets目录下,由于有大小限制(1M),所以改名成b.mp3(因为mp3,jpg,png,mp4等不会检查,不会限制大小), ...
- Android M(6.0) 权限爬坑之旅
坑一:用Android5.0编译的apk,在Android6.0上运行完全没有问题. 在Android6.0以上才需要在运行时请求权限,在旧Android版本上保留原有逻辑,安装时授予权限. 用旧版本 ...
- RFC 文档(中文与英文)
http://man.chinaunix.net/develop/rfc/default.htm https://www.rfc-editor.org/retrieve/ http://www.iet ...
