web框架详解之tornado 一 模板语言以及框架本质
一、概要
Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞
式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。 Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll
的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed
的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。
(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题请点击我
下载安装:
pip3 install tornado
源码安装
https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
Tornado 各主要模块
web - FriendFeed 使用的基础 Web 框架,包含了 Tornado 的大多数重要的功能
escape - XHTML, JSON, URL 的编码/解码方法
database - 对 MySQLdb 的简单封装,使其更容易使用
template - 基于 Python 的 web 模板系统
httpclient - 非阻塞式 HTTP 客户端,它被设计用来和 web 及 httpserver 协同工作
auth - 第三方认证的实现(包括 Google OpenID/OAuth、Facebook Platform、Yahoo BBAuth、FriendFeed OpenID/OAuth、Twitter OAuth)
locale - 针对本地化和翻译的支持
options - 命令行和配置文件解析工具,针对服务器环境做了优化 底层模块
httpserver - 服务于 web 模块的一个非常简单的 HTTP 服务器的实现
iostream - 对非阻塞式的 socket 的简单封装,以方便常用读写操作
ioloop - 核心的 I/O 循环
Tornado 各主要模块
二、框架的初步使用
二、 #!/usr/bin/env python
# -*- coding:utf- -*- # 首先导入模块
import tornado.ioloop
import tornado.web
# 让这个类继承 执行
class MainHandler(tornado.web.RequestHandler):
def get(self):
# self.write("Hello, world")
# 默认在当前的目录中寻找
self.render("s1.html")
# 然后创建这个对象
# 路由映射,也可以叫做路由系统
application = tornado.web.Application([
(r"/index", MainHandler),
])
if __name__ == "__main__":
# 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
application.listen()
tornado.ioloop.IOLoop.instance().start()
快速上手
流程说明:
上面执行流程:首先导入模块,之后创建类,然后通过路由系统监听端口并且执行,用户连接就执行get等方法来给用户返回数据
三、框架的方法和配置
配置:
import tornado.ioloop
import tornado.web
# import uimodules as md
# import uimethods as mt class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world") settings = {
'template_path': 'views', # html文件
'static_path': 'statics', # 静态文件(css,js,img)
'static_url_prefix': '/statics/',# 静态文件前缀
'cookie_secret': 'suoning', # cookie自定义字符串加盐
# 'xsrf_cookies': True, # 防止跨站伪造
# 'ui_methods': mt, # 自定义UIMethod函数
# 'ui_modules': md, # 自定义UIModule类
} application = tornado.web.Application([
(r"/", MainHandler),
], **settings) if __name__ == "__main__":
application.listen()
tornado.ioloop.IOLoop.instance().start()
hello world
、首先配置字典
配置模板路径的配置,其中template是自己创建的目录名字,字典中的key是不能更改的
settings={
“template_path”:”template”,
}
、添加配置文件
在路由映射里面添加配置文件 (路由系统的两个参数,第一个刹那函数是接受一个列表,第二个 参数是接受一个配置)
application=tonardo.web.Application([(r”/index”,MainHandler)],**settings)
、 配置静态文件路径
如果css和js需要导入到html文件中,就需要在tonardo中配置静态文件路径,要不然就不会生效
settings={
“static_path”:”static”,
} 、给url添加前缀
在settings里面添加“static_url_prefix”:”/sss/”, 后面的这三个sss要和html中的文件href路径前面一样
配置文件说明
方法:请求来时,程序会用正则匹配相应路由地址,并交付于 tornado.web.RequestHandler 的子类处理;子类会根据请求方式(post / get / delete ...)的不同调用并执行相应的方法,方法返回字符串内容并发送到浏览器。
self.write("") # 把字符串发送到客户端
self.render("index.html") # 返回html文件,调用render_string(),内部其实是打开并读取文件,返回内容 如果把html单独放到一个目录中,那么需要在render方法中加上路径
self.redirect("s1.html",permanent=False) # 跳转重定向,参数代表是否永久重定向 name = self.get_argument("name") # 获取客户端传入的参数值
name = self.get_arguments("name") # 获取多个值,类别形式
file = self.request.files["filename"] # 获取客户端上传的文件 raise tornado.web.HTTPError() # 返回错误信息给客户端
方法
tonardo配置方法:
、 self.write(“”):这里面填入字符串
、 self.render(“s1.html”):这个是把同目录的s1.html内容引入,用户连接tonardo的时候返回的内容
、 如果把html文件单独放入一个目录的话,那么需在render方法里面加上路径
如:把s1文件放入到目录tempalete目录中,那么执行self.render(“template/s1.html”) 、 但是文件html文件太多,不应该每个都加上路径,那么就可以配置文件
、首先配置字典
配置模板路径的配置,其中template是自己创建的目录名字,字典中的key是不能更改的
settings={
“template_path”:”template”,
}
、添加配置文件
在路由映射里面添加配置文件 (路由系统的两个参数,第一个刹那函数是接受一个列表,第二个 参数是接受一个配置)
application=tonardo.web.Application([(r”/index”,MainHandler)],**settings) 、 配置静态文件路径
如果css和js需要导入到html文件中,就需要在tonardo中配置静态文件路径,要不然就不会生效
settings={
“static_path”:”static”,
} 、给url添加前缀 这个不太重要
在settings里面添加“static_url_prefix”:”/sss/”, 后面的这三个sss要和html中的文件href路径前面一样
总结
四、写tornado框架
写tornado框架
1、 首先导入tornado
2、 继承里面的类,书写方法
3、 创建对象
4、 配置文件、模板路径
下面是利用模板语言,用输入的数据展示出来:实例贴吧,发帖就展示出来
1、 写上form表单,用于用户提交内容,用post方法提交
2、 用self.get_argument(“”)方法获取用户输入的内容,并且把获取的内容添加到列表中
3、 用模板语言,来遍历这个列表。最后随着页面展现出来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/sss/commons.css"/>
</head>
<body>
<h1>提交内容</h1>
<form method="post" action="/index">
<input type="text" name="xx"/>
<input type="submit" value="提交"/>
<h1>展示内容</h1>
<ul>
{% for item in xxoo %}
<li>{{item}}</li>
{% end %}
</ul>
</form>
</body>
</html>
HTML代码
#!/usr/bin/env python
# -*- coding:utf- -*- # 首先导入模块
import tornado.ioloop
import tornado.web
# 让这个类继承 执行 INPUT_LIST=[]
class MainHandler(tornado.web.RequestHandler):
def get(self):
# 、打开s1.html文件,读取内容(包含特殊语法)
#、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
#、得到新的字符串
#、返回给用户
self.render("s1.html",xxoo=INPUT_LIST)
def post(self, *args, **kwargs):
# 这个方法是接收用户输入的内容
name=self.get_argument("xx")
INPUT_LIST.append(name)
self.render("s1.html",xxoo=INPUT_LIST)
settings={
"template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
"static_path":"static", #配置静态文件路径
"static_url_prefix":"/sss/", #为url加上前缀
}
# 然后创建这个对象
# 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
application = tornado.web.Application([
(r"/index", MainHandler),
],**settings)
if __name__ == "__main__":
# 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
application.listen()
tornado.ioloop.IOLoop.instance().start()
python代码
上面执行流程
、 用户访问,执行get方法展现
、 用户通过form表单,接收到用户输入的内容,存放到列表中,然后执行post方法,跳转到这个页面返回给用户页面和列表
、注意这个是前台把内容发送到后台
执行流程
写完上面的程序,那么就可以对其进行补充:通过self.get_argument(“xxx”)# 获取用户提交的数据
区别:
对于GET,URL中传输数据
对于POST, 只能通过提交传输数据
post和get区别
下面就是在get方法中通过get_argument的方法来获取用户的数据通过列表的方式来返回给用户,注意这里的argument中的参数,None 默认为空
INPUT_LIST=[]
class MainHandler(tornado.web.RequestHandler):
def get(self):
# 、打开s1.html文件,读取内容(包含特殊语法)
#、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
#、得到新的字符串
#、返回给用户
name=self.get_argument("xx",None)
if name:
INPUT_LIST.append(name)
self.render("s1.html",xxoo=INPUT_LIST)
get_argument用法
五、模板语言
模板语言分为三类
第一种是{% for iyem in xxoo%} 代码块
需要注意的是这种代码的的结尾都必须要有{% end %},并且要和循环的对应类似于shell中的循环
<h1>展示内容</h1>
<ul>
{% for item in xxoo %}
{% if item=="aa" %}
<li style="background-color: red;">{{item}}</li>
{% else %}
<li>{{item}}</li>
{% end %}
{% end %}
</ul>
第二种是<li>{{item}}</li>代表的是表达式或者值
第三种是自定义的
自定义函数里面有两类 定义什么就返回什么
1、 uimethod
首先在html中自己定义一个执行的函数方法 {{方法名(参数)}}
<form method="get" action="/index">
<input type="text" name="xx"/>
<input type="submit" value="提交"/>
<h1>展示内容</h1>
<h1>{{npm}}</h1>
<h3>{{func(npm)}}</h3>
</body>
</html>
html文件
之后自己定义一个单独的文件(模块),内容为在html自己定义的函数 ,文件名为
#/usr/bin/env python
#-*- coding:utf- -*-
def func(self,arg):
print(arg)
# 返回给用户大写变小写
return arg.lower() 上面的函数名为func,参数arg是传入的npm --》get方法中self.render(npm=”NPM=”)
uimethod.py
之后在settings字典中添加”ui_methods”:mt,并且导入上面创建的模块
#!/usr/bin/env python
# -*- coding:utf- -*- # 首先导入模块
import tornado.ioloop
import tornado.web
import uimethod as mt
# 让这个类继承 执行 INPUT_LIST=[]
class MainHandler(tornado.web.RequestHandler):
def get(self):
# 、打开s1.html文件,读取内容(包含特殊语法)
#、xxoo=INPUT_LIST && 读取内容(包含特殊语法)
#、得到新的字符串
#、返回给用户
name=self.get_argument("xx",None)
if name:
INPUT_LIST.append(name)
self.render("s1.html",npm="NPM888",xxoo=INPUT_LIST)
# def post(self, *args, **kwargs):
# # 这个方法是接收用户输入的内容
# # name=self.get_argument("xx",None)
# # INPUT_LIST.append(name)
# self.render("s1.html",npm="NPM",xxoo=INPUT_LIST)
settings={
"template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
"static_path":"static", #配置静态文件路径
"static_url_prefix":"/sss/", #为url加上前缀
"ui_methods":mt
}
# 然后创建这个对象
# 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
application = tornado.web.Application([
(r"/index", MainHandler),
],**settings)
if __name__ == "__main__":
# 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
application.listen()
tornado.ioloop.IOLoop.instance().start()
后台代码
总结:
定义
首先在html中自定义函数,然后创建一个模块,内容就是自定义函数的执行方法,
注册
最后在tornado中导入这个模块,重命名,并且加到配置中
总结
2、 uimodule
需要写一个类,这个类必须继承uimodule
首先自己定制一个模块,名字为uimodule,里面要写上类,并且这个类要继承UIModule
#!/usr/bin/env python
# -*- coding:utf- -*-
from tornado.web import UIModule
from tornado import escape class custom(UIModule): def render(self, *args, **kwargs):
return ""
模块代码
#!/usr/bin/env python
# -*- coding:utf- -*- # 首先导入模块
import tornado.ioloop
import tornado.web
import uimethod as mt
import uimodule as md
# 让这个类继承 执行 INPUT_LIST=[]
class MainHandler(tornado.web.RequestHandler):
def get(self):
name=self.get_argument("xx",None)
if name:
INPUT_LIST.append(name)
self.render("s1.html",npm="NPM888",xxoo=INPUT_LIST)
settings={
"template_path":"template", #模板路径的配置,value是目录的名字,但是key不能改名字
"static_path":"static", #配置静态文件路径
"static_url_prefix":"/sss/", #为url加上前缀
"ui_methods":mt, #注册
"ui_modules":md, #注册
}
# 然后创建这个对象
# 路由映射,也可以叫做路由系统,下面是参数第一个是接受一个列表,第二个接受一个配置
application = tornado.web.Application([
(r"/index", MainHandler),
],**settings)
if __name__ == "__main__":
# 下面是创建了socket,循环,以及epoll io多路复用 socket运行起来
application.listen()
tornado.ioloop.IOLoop.instance().start()
注册代码
在html中自定义,即{% module 类()%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/sss/commons.css"/>
</head>
<body>
<h1>提交内容</h1>
<form method="get" action="/index">
<input type="text" name="xx"/>
<input type="submit" value="提交"/>
<h1>展示内容</h1>
<h1>{{npm}}</h1> <h3>{{func(npm)}}</h3>
<h3>{% module custom() %}</h3>
</form>
</body>
</html>
html代码
总结:通过自定义来可以用python语言来写模板语言的功能
uimethod:
这个是自定义函数,通过函数来返回给用户数据
uimodule:
这个是自定义类的,通过类中的函数来给用户返回数据
注意:如果get方法中传入参数,和模板函数相关,那么post也要有这个参数
总结
模板方法
escape都是转义的功能
- escape: tornado.escape.xhtml_escape 的別名
- xhtml_escape: tornado.escape.xhtml_escape 的別名
- url_escape: tornado.escape.url_escape 的別名
- json_encode: tornado.escape.json_encode 的別名 用作json处理的
- squeeze: tornado.escape.squeeze 的別名
- linkify: tornado.escape.linkify 的別名 生成a标签的
- datetime: Python 的 datetime 模组 用的python的datatime模块
- handler: 当前的 RequestHandler 对象 self.self,handler是self对象
- request: handler.request 的別名 self封装的所有的request信息
- current_user: handler.current_user 的別名 所有的handler都是self对象
- locale: handler.locale 的別名
- _: handler.locale.translate 的別名
- static_url: for handler.static_url 的別名 这个是做缓存用的
- xsrf_form_html: handler.xsrf_form_html 的別名 防止跨站请求用的
- static_url: for handler.static_url 的別名 这个是做缓存用的
具体用法: 在静态文件前面添加
下面黄色部分
外部是单引号,之后两个大括号,之后小括号是应用的静态文件名字
‘{{static_url(“文件名”)}}’
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href='{{ static_url("commons.css")}} '/>
</head>
<body>
<div>提交内容</div>
<form method="get" action="/index">
<input type="text" name="xx"/>
<input type="submit" value="提交"/>
<h1>展示内容</h1>
<h1>{{npm}}</h1> <h3>{{func(npm)}}</h3>
<h3>{% module custom() %}</h3>
<ul>
{% for item in xxoo %}
{% if item=="aa" %}
<li style="background-color: red;">{{item}}</li>
{% else %}
<li>{{item}}</li>
{% end %}
{% end %}
</ul>
</form>
</body>
</html>
模板引用静态文件用法
作用:用户浏览器接收数据,如果md5变化了,那么缓存就更新为静态文件做缓存,从浏览器中查看,下面的v后面的内容是md5序列号
六、tornado框架之模板引擎的本质
模板引擎在内部就是做了字符串拼接
模板引擎的本质 字符窜分割:
本质就是处理html文件内容将html文件内容转换成函数,然后为该函数提供全局变量环境(即:我们想要嵌套进html中的值和框架自带的值),再之后执行该函数从而获取到处理后的结果,再再之后则执行UI_Modules继续丰富返回结果,例如:添加js文件、添加js内容块、添加css文件、添加css内容块、在body内容第一行插入数据、在body内容最后一样插入数据,最终,通过soekct客户端对象将处理之后的返回结果(字符串)响应给请求用户。
上图就是把左侧的html代码转换成字符串,然后用接受一个字符串通过compile和exec执行,放到一个字典中,然后通过字典执行转化成
函数的方法转换成函数
#/usr/bin/env python
#-*-coding:utf- -*- namespace={'name':'pyrene','data':[,,],}
code='''def hellocute():return "name %s,age %d" %(name,data[0],)''' #把code编译成字节码对象,第二个参数是声明类型,第三个参数表示这是一个序列类型
#编译成函数
func=compile(code,'<string>',"exec")
#执行,把func放入到namespace字典里面
exec(func,namespace) result=namespace['hellocute']() print(result)
例子
补充知识:
1、Python标准库:内置函数compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
source 是编译的对象
filename 声明该对象的类型
mode 用什么类型来编译
2、内置函数exec(object[, globals[, locals]])
执行函数,把对象放入到 后面变量中
compile只编译字符串代码,不做任何的执行,但是可以编译表达式和语句
exec函数是只执行语句代码,不执行表达式代码,因为他没有返回值
eval 只执行表达式代码,不执行语句代码x = eval('%d + 6' % x)
. #exec()
.
. exec('if True: print(100)')
. exec('''''
. x =
. if x > :
. print(x + )
. ''')
例子
web框架详解之tornado 一 模板语言以及框架本质的更多相关文章
- web框架详解之 tornado 四 模板引擎、session、验证码、xss
一.模板引擎 基本使用 继承,extends 页面整体布局用继承 导入,include 如果是小组件等重复的那么就用导入 下面是目录 首先在controllers里面创建一个文件,文件里面是页面类 # ...
- web框架详解之tornado 三 url和分页
一.代码目录构建 controllers :处理业务逻辑的 account:处理账户相关的 上面目录作用和内容 controllers 包 :处理业务逻辑的 account:处理账户相关的 home ...
- web框架详解之tornado 二 cookie
一.tornado之cookie一 目录: <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- Solon 框架详解(十一)- Solon Cloud 的配置说明
Solon 详解系列文章: Solon 框架详解(一)- 快速入门 Solon 框架详解(二)- Solon的核心 Solon 框架详解(三)- Solon的web开发 Solon 框架详解(四)- ...
- Spark2.1.0——内置Web框架详解
Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...
- (转) shiro权限框架详解06-shiro与web项目整合(上)
http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...
- JAVA Eclipse使用Maven构建web项目详解(SSM框架)
tips: 启动项目后,welcome-file的链接即为测试用例 部署maven web项目 Eclipse使用Maven构建web项目详解 pom.xml添加webapp依赖: <depen ...
- Solon 框架详解(十)- Solon 的常用配置
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- jQuery Validate验证框架详解
转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...
随机推荐
- C#利用SharpZipLib解压或压缩文件(支持多层目录递归压缩)
需要下载ICSharpCode.SharpZipLib.dll using System; using System.Collections.Generic; using System.Linq; u ...
- PHP面试题及答案解析(6)—PHP网络编程
1.禁用COOKIE后SEESION还能用吗? 可以,COOKIE和SESSION都是用来实现会话机制的,由于http协议是无状态的,所以要想跟踪一个用户在同一个网站之间不同页面的状态,需要有这么一个 ...
- SVN服务端的安装搭建(Linux)
在CentOS下安装 SVN 大多数 GNU/Linux 发行版系统自带了Subversion ,所以它很有可能已经安装在你的系统上了.可以使用下面命令检查是否安装了. svn --version 如 ...
- Android版CSDN发现的一些问题
作为CSDN的忠有用户,在他一推出这款APP以后.就下载了使用,近期发现了一些个问题,在此提出来.希望看到或者遇到同样问题的,提出你们的解决方式. 在CSDN手机版的首页上,我 ...
- flume-ng tmp
flume-ng 是一个分布式,高可用的日志收集系统.主要用来将分布在不同服务器上的业务日志汇总在一个集中的数据存储中心 一 安装与环境配置 下载地址 http://flume.apache.org/ ...
- hbase的数据模型
hbase类似bigTable是一个分布式的数据库,它是一个稀疏的,长期存储的,多维的,排序的映射表,这张表的索引是行关键字,列关键字,时间戳.hbase中的数据都是字符串,没有类型. ...
- 一个简单的数据增量更新策略(Android / MongoDB / Django)
我在做个人APP - CayKANJI - 的时候遇到一个问题: 如何增量式地把日语汉字数据地从server更新到APP端,即每次用户运行更新操作时,仅仅获取版本号高于本地缓存的内容. 数据格式 为了 ...
- 【Mac系统】istatmenus6.20下载以及激活
下载地址:https://pan.baidu.com/s/1-2-yw2NnOlGJ46D536t5uQ iStat Menus 的激活密码: Email: 982092332@qq.com SN: ...
- 【JMeter4.0学习(三)】之SoapUI创建WebService接口模拟服务端以及JMeter对SOAP协议性能测试脚本开发
目录: 创建WebService接口模拟服务端 下载SoapUI 新建MathUtil.wsdl文件 创建一个SOAP项目 接口模拟服务端配置以及启动 JMeter对SOAP协议性能测试脚本开发 [阐 ...
- 【Axure插件】之浏览器打开失败
下载地址:https://files.cnblogs.com/files/Owen-ET/AxureRP_for_chorme_0_6_2.xml 下载后的文件后缀修改为:AxureRP_for_ch ...