tornado 基本功能

Tornado的特点

Tornado(龙卷风)和Django一样是Python中比较主流的web框架,Tornado 和现在的主流 Web 服务器框架也有着明显的区别:Tornado自带socket,并且实现了异步非阻塞,而且对WebSocket协议天然支持。

相对于其他Python网络框架,它有如下特点

  • 完整的web框架:与Django、Flask等一样,Tornado也提供URL路由映射、Request上下文、基于模板的页面渲染技术等开发Web应用的必备工具。
  • 是一个高效的网络库,性能与Twisted、Gevent等底层Python框架想媲美:提供了异步I/O支持、超时事件处理。这使得Tornado除了可以作为Web应用服务器框架,还可以用来做爬虫、游戏服务器等后台应用。
  • 提供高效的内部HTTP服务器:虽然其他框架也提供了内部HTTP服务器,但它们的HTTP服务器由于性能原因只能用于测试环境。而Tornado的HTTP服务器与Tornado异步调用紧密结合,可以之间用于生产环境。
  • 完备的websocket支持:WebSocket是HTML5的一种新标准,实现了浏览器与服务器之间的双向实时通信。

由于Tornado的上述特点,Tornado常被用作大型站点的接口服务框架,而不像Django那样着眼于简历完整的大型网站。

Tornado的基本组成

Tonado由 路由系统、视图、模板语言等组成,如果习惯了使用Django你会感觉它功能单薄,但是只有这样才能足够轻量,如果用到什么功能就自己去GitHub上找现成的插件,或者自实现;以下将对这些基本组件进行逐一介绍。

Django功能概览:
  socket:有 
  中间件:无(使用Python的wsgiref模块)
  路由系统:有
  视图函数:有
  ORM操作:有
  模板语言:有
  simple_tag:有
  cokies:有
  session:有
  csrf:有
  xss:有
  其他:缓存、信号、Form组件、ModelFormm、Admin

tornado功能概览:
  socket:有(异步非阻塞、支持WebScoket)
  路由系统:有
  视图函数:有
  静态文件:有
  ORM操作:无
  模板语言:有
  simple_tag:有,uimethod,uimodule
  cokies:有
  session:无
  csrf:有
  xss:有
  其他:无
Django Tornado
socket
路由系统
视图函数
静态文件
模板语言
ORM操作
simple_tag 有uimethod,uimodule
cokies
session
csrf
xss
其他 缓存、信号、Form组件、ModelFormm、Admin

Tornado的基本功能

安装:

pip install tornado

基本流程

import tornado.ioloop
import tornado.web

# 注意继承RequestHandler 而不是redirectHandler
class MainHandler(tornado.web.RequestHandler):
    
    def get(self):
        """get请求"""
        self.write("Hello World!")
        
def make_app():
    return tornado.web.Application(
    	[(r"/index", MainHandler), ]		# 路由映射到类
    )

def main():
    app = make_app()	# URL路由映射
    app.listen(8888)	# 创建1个socket对象,监听8888端口
    tornado.ioloop.IOLoop.instance().start()  
    # 启动IOLoop,该函数一直运行且不退出,用于处理完所有客户端的访问请求
    # 相当于conn, addr=socket.accept()进入监听状态

第一步:执行脚本,监听 8888 端口

第二步:浏览器客户端访问 /index --> http://127.0.0.1:8888/index/

第三步:服务器接受请求,根据URL的访问映射到RequestHandler的子类,并交由对应的类MainHandler处理该请求

第四步:MainHandler类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法

第五步:方法返回值的字符串内容发送浏览器

配置

setings={
'template_path':'templates',	# 配置模板路径
'static_path':'static',     	# 配置静态文件存放的路径
'static_url_prefix':'/static/',	 # 在模板中引用静态文件路径时使用的别名 注意是模板引用时的别名,必须以/开头以/结尾
"xsrf_cookies": True,               # 使用xsrf认证
'cookie_secret' :'xsseffekrjewkhwy'	# cokies加密时使用的盐
}

# 加载路由和配置
application=tornado.web.Application(
    [(r'/login/',LoginHandler) ,	
     (r'/index/',IndexHandler) ,	
    ],		# 参数1 路由系统
    **setings	# 参数2 配置文件
)

路由系统

与Django类似,用正则字符串进行路由匹配。有两种:固定字符串路径和参数字符串路径。

动态路由:

app=tornado.web.Application(
    [
        (r'^/index/$',MainHandler),
        (r'^/index/(\d+)$',MainHandler), #url传参
    ]
)

域名匹配:

#支持域名匹配  www.xxx.com:8888/index/333333
app.add_handlers('www.xxx.com',[

        (r'^/index/$', MainHandler),
        (r'^/index/(\d+)$', MainHandler),
])

反向生成url:

app.add_handlers('www.zhanggen.com',[
        (r'^/index/$', MainHandler,{},"name1"), #反向生成url
        (r'^/index/(\d+)$', MainHandler,{},"name2"),
])
class MainHandler(tornado.web.RequestHandler):
    def get(self,*args,**kwargs):
        url1=self.application.reverse_url('name1')
        # reverse_url 反向解析
        url2 = self.application.reverse_url('name2', 666)
        print(url1,url2)
        self.write('hello word')

视图 RequestHandler

tornado的视图才有CBV模式,url匹配成功之后先 视图执行顺序为 initialize 、prepare、get/post/put/delete、finish;

接入点函数:需要子类继承并定义具体行为的函数在RequestHandler中被称为接入点函数(Entry Point),例如前面的get()函数就是接入点函数。

RequestHandler.initialize():

该方法被子类重写,实现RequestHandler子类实例的初始化过程。可以为该函数传递参数,参数来源于配置URL映射时的定义。

class ProfileHandler(tornado.web.RequestHandler):
    
    def initialize(self, database):
        self.database = database
        
    def get(self):
        pass
    
app = tornado.web.Application([(r'/account',ProfileHandler, dict(database="c:\\example.db"))])

# initialize有参数database,在定义URL映射时以dict方式给出
RequestHandler.prepare():

prepare()方法用于调用请求处理(get,post等)方法之前的初始化处理,可以根据实际需求进行重写。通常可以用prepare()方法做资源初始化操作。

RequestHandler.finish():

finish()方法用于请求处理结束后的一些清理工作,例如可以做清理对象占用的内存或者关闭数据库连接等。

RequestHandler.get()/post():

每个http action在RequestHandler中都已单独的函数进行处理,都是以对应的HTTP方法小写的方式名命。

  • RequestHandler.get(self,*args,**kwargs)
  • RequestHandler.head(self,*args,**kwargs)
  • RequestHandler.post(self,*args,**kwargs)
  • RequestHandler.delete(self,*args,**kwargs)
  • RequestHandler.patch(self,*args,**kwargs)
  • RequestHandler.put(self,*args,**kwargs)
  • RequestHandler.options(self,*args,**kwargs)
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
    def initialize(self): #1
        print()

    def prepare(self):
        pass

    def get(self,*args,**kwargs):
        self.write('hello word')

    def post(self, *args, **kwargs):
        pass

    def finish(self, chunk=None):
        pass
        super(self,MainHandler).finish()

请求相关输入捕获

输入捕获是指在RequestHandler中用于获取客户端输入的工具函数和属性,比如获取url中的参数、post提交的参数等。

  • self.get_argument('user'): 获取GET和POST请求携带的参数

  • self.get_arguments('user_list'):获取GET和POST请求参数列表(如chebox标签和select多选)

  • self.get_query_argument('user'):获取GET请求携带的参数

  • self.get_query_arguments('user_list'):获取GET请求参数列表(如chebox标签和select多选)

  • self.get_body_argument('user'):获取POST请求携带的参数

  • self.get_body_arguments('user_list'):获取POST请求参数列表(如chebox标签和select多选)

  • self.request.body.decode('utf-8'):获取json数据

  • self.get_cookie(name, default=None) : 根据cookie名称获取cookie值

  • self.request :返回itornado.httputil.HTTPServerRequest对象实例的苏醒,通过该对象可以获取关于HTTP请求的一切信息,

    import tornado.web
    
    class DetailHandler(tornado.web.RequestHandler):
        
        def get(self):
            remote_ip = self.request.remote_ip	# 获取客户端的IP地址
            host = self.request.host	# 获取请求的主机地址
            
    

技巧:在一般情况下 用self.get_argument('user',None)/self.get_arguments('user',None)即可,因为它们不管是GET还是POST,都可以用它们来获取请求携带的参数,相当于是一种合集。

:以上取值方式如果取不到值就会报错,可以设置取不到值就取None;(例如 self.get_argument('user',None))

输出响应

输出响应函数是指一组为客户端生成处理结果的工具函数,扩展url的处理结果。下面列举常用的三种:

  • self.write(chunk): 一般情况下,用于输出字符串到客户端。如果是一个字典,则会以JSON格式发送给客户端,同时将请求头中的Content_type设置成 application/json。
  • self.render(template_name, **kwargs): 用于响应页面,用给定的参数渲染模板,可以在本函数中传入模板文件名称和模板的参数。
  • self.redirect(url,): 重定向页面。

模板语言

tornado的模板语言和python语法一致。

登录示例:

import tornado.ioloop
import tornado.web

class LoginHandler(tornado.web.RequestHandler): 
    def get(self):
        self.render('login.html')

settings={
'template_path':'templates',#配置模板路径
'static_path':'static',     #配置静态文件存放的路径
'static_url_prefix':'/static/' #在模板中引用静态文件路径时使用的别名 注意是模板引用时的别名
}
app=tornado.web.Application([
                        (r'/login/',LoginHandler) #参数1 路由系统
                                     ],
                        **settings	#参数2 配置文件
                            )


if __name__ == '__main__':
    app.listen(8888)     #创建1个socket对象
    tornado.ioloop.IOLoop.instance().start()

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/dist/css/bootstrap.css">
    <title>Title</title>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-5 col-md-offset-3">
            <form method="post" >
                  <div class="form-group">
                    <label for="exampleInputEmail1">用户名</label>
                    <input type="email" class="form-control" id="exampleInputEmail1" placeholder="用户名">
                  </div>
                  <div class="form-group">
                    <label for="exampleInputPassword1">密码</label>
                    <input type="password" class="form-control" id="exampleInputPassword1" placeholder="密码">
                  </div>
                  <button type="submit" class="btn btn-default">提交</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

引入静态文件

通过别名引入静态文件:

<link rel="stylesheet" href="/static/coment.css">

static_url()方式一个如静态文件:

<link rel="stylesheet" href='{{static_url("dist/css/bootstrap.css") }}'>

通过static_url()方法引入静态文件的好处:

1、使用static_url()可以不用考虑静态文件修改之后造成引用失效的情况;

2、还会生成静态文件url会有一个v=...的参数,这是tornado根据静态文件MD5之后的值,如果后台的静态文件修改,这个值就会变化,前端就会重新向后台请求静态文件,保证页面实时更新,不引用浏览器缓存;

上下文

如果模板语言中声明了变量,上下文对象必须对应传值,如果没有就设置为空,否则会报错;

self.render('login.html',**{'erro_msg':'' }) #模板中声明了变量,视图必须传值,如果没有就设置为空;
posted @ 2020-08-27 12:56  SensorError  阅读(419)  评论(0编辑  收藏  举报