Tornado框架——1

时间:Aug. 31, 2017 分类:

目录:

Tornado

Tornado是一种Web服务器软件的开源版本。Tornado和现在的主流Web服务器框架(包括大多数Python的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其非阻塞的方式和对epoll的运用,Tornado每秒可以处理数以千计的连接,因此Tornado是实时Web服务的一个理想框架。

安装tornado

使用tornado

第一个tornado代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web


class MainHandler(tornado.web.RequestHandler):    #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候,执行的get方法
        self.write("Hello, world")

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
])


if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

启动后访问结果

访问其他url则会返回404

linux更直观一点

[root@why ~]# curl 127.0.0.1:8888/index
Hello, world
[root@why ~]# curl 127.0.0.1:8888/in
<html><title>404: Not Found</title><body>404: Not Found</body></html>

如果执行post方法需要

    def post(self, *args, **kwargs):                  
        self.write("Hello, world")

返回html

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web


class MainHandler(tornado.web.RequestHandler):      #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        #self.write("Hello, world")
        self.render("index.html")                     #返回html

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
])


if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

示例index.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Hello, world</h1>
</body>
</html>

访问结果

默认情况下在当前目录寻找,如果不在这个目录可以写相对路径

例如 template/index.html

配置html的目录

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web


class MainHandler(tornado.web.RequestHandler):      #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        #self.write("Hello, world")
        self.rander("xxx.html")                     #返回html

settings = {
    'template_path': 'template',                    #配置模板路径
    'static_path': 'static',                        #静态文件路径
    #'static_path': '/why/',                        #静态目录前缀
}

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
], **settings)                                      #加载settings

if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

示例目录结构

html默认会在template_path下寻找,而css和js等会在static_path下寻找

href="static/commons.css"

静态文件缓存处理可以使用href="{{static_url('/commons.css')}}"

前端html和后端tornado进行交互

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web

input_list = []

class MainHandler(tornado.web.RequestHandler):    #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        self.render("index.html",name=input_list)    #返回html
    def post(self,*args,**kwargs):
        show = self.get_argument('show')
        input_list.append(show)
        self.render("index.html",name=input_list)

settings = {
    'template_path': 'template',                    #配置模板路径
    'static_path': 'static',                        #静态文件路径
}

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
], **settings)                                      #加载settings

if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

render方法在获取多个参数的时候,执行以下操作

  1. 打开index.html文件,读取内容和其内部的特殊语法
  2. 获取到字典input_list,转化成name字典执行html内部的for循环,就是俗称的渲染
  3. 得到新的字符串
  4. 进行展示

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>SHOW</h1>
    <form action="/index" method="post">
        <input type="text" name="show">
        <input type="submit" value="提交">
    </form>
    <ul>
        {% for item in name %}
        <li>{{item}}</li>
        {% end %}
    </ul>
</body>
</html>

效果展示

通过get方法实现交互

tornado代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web

input_list = []

class MainHandler(tornado.web.RequestHandler):    #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        show = self.get_argument('show',None)
        if show:
            input_list.append(show)
        self.render("index.html",name=input_list)    #返回html
    def post(self,*args,**kwargs):
        show = self.get_argument('show')
        input_list.append(show)
        self.render("index.html",name=input_list)

settings = {
    'template_path': 'template',                    #配置模板路径
    'static_path': 'static',                        #静态文件路径
}

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
], **settings)                                      #加载settings

if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

模板语言的三种形式

  1. {{item}}直接调用
  2. {% if for %}和{% end %}代码段
  3. uimethod和uimodule进行自定义

ui_method

ui_method不需要进行继承

tornado代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web
import uimethod

input_list = []

class MainHandler(tornado.web.RequestHandler):    #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        show = self.get_argument('show',None)
        if show:
            input_list.append(show)
        self.render("index.html",name=input_list)    #返回html
    def post(self,*args,**kwargs):
        show = self.get_argument('show')
        input_list.append(show)
        self.render("index.html",name=input_list)

settings = {
    'template_path': 'template',                    #配置模板路径
    'static_path': 'static',                        #静态文件路径
    'ui_methods': uimethod,                          #自定义
}

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
], **settings)                                      #加载settings

if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

uimethod.py代码

def funa(self,arg):
    return 'uimethod'

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>SHOW</h1>
    <form action="/index" method="post">
        <input type="text" name="show">
        <input type="submit" value="提交">
    </form>
    <h1>{{ funa('123') }}</h1>
    <ul>
        {% for item in name %}
        <li>{{item}}</li>
        {% end %}
    </ul>
</body>
</html>

展示效果

ui_module

uimodule.py 需要继承UIModule类

tornado代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from tornado.web import UIModule

class funb(UIModule):

    def render(self, *args, **kwargs):
        return 'uimodule'
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import tornado.ioloop                               #导入模块
import tornado.web
import uimethod
import uimodule

input_list = []

class MainHandler(tornado.web.RequestHandler):    #继承tornado.web.RequestHandler
    def get(self):                                  #直接访问的时候
        show = self.get_argument('show',None)
        if show:
            input_list.append(show)
        self.render("index.html",name=input_list)    #返回html
    def post(self,*args,**kwargs):
        show = self.get_argument('show')
        input_list.append(show)
        self.render("index.html",name=input_list)

settings = {
    'template_path': 'template',                    #配置模板路径
    'static_path': 'static',                        #静态文件路径
    'ui_methods': uimethod,                          #自定义
    'ui_modules': uimodule,                          #自定义
}

application = tornado.web.Application([             #创建tornado.web.Application对象
    (r"/index", MainHandler),                       #当发送url请求的时候,对检查是否匹配,然后路由到对应的类的get,post等方法(路由映射)
], **settings)                                      #加载settings

if __name__ == "__main__":
    application.listen(8888)                        #创建一个socket
    tornado.ioloop.IOLoop.instance().start()        #使用epoll,IO多路复用循环

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>SHOW</h1>
    <form action="/index" method="post">
        <input type="text" name="show">
        <input type="submit" value="提交">
    </form>
    <h1>{{ funa('123') }}</h1>
    <h1>{% module funb('123') %}</h1>
    <ul>
        {% for item in name %}
        <li>{{item}}</li>
        {% end %}
    </ul>
</body>
</html>

展示效果

tornado内置模板函数

tornado自定义了一些函数,字段和类供模板使用

  • 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 模组
  • handler: 当前的 RequestHandler 对象(handler=self)
  • request: handler.request 的別名(request=self.request)
  • current_user: handler.current_user 的別名
  • locale: handler.locale 的別名
  • _: handler.locale.translate 的別名
  • static_url: for handler.static_url 的別名(用于缓存,md5值)
  • xsrf_form_html: handler.xsrf_form_html 的別名(防止跨站请求伪造,防止xss攻击)

其实本质上都是ui_methodui_module

实现静态资源缓存

html在head标签加入

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

why.css代码

h1{
    color: red
}

目录结构

展示结果

通过开发模式看

在浏览器收到的文件名就是why.css

进行静态资源缓存

html修改为

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

通过开发模式看

可以看到css名后有后缀,为其的md5值,所以只有当css修改后才会改变,用于缓存

注意tornado的index.html修改后需要重启。