Tornado输入与输出

输出

write方式

前面介绍基本的输出,可以通过write把字符串输出到浏览器,除此之外,write还可以把那些东西输出到浏览器呢?

  1. 字节bytes
self.write(b'Tornado<br/>')  #bytes 字节
  1. 字典dict
user = {'name':'cainiao','age':18}  #字典
self.write(user)   #字典
  1. 字符Unicode
 self.write('22<br/>33')
  1. 其他
li = [1,2,3,4]
import json

li = json.dumps(li)  #列表,需要序列化成json字符
self.write(li)
代码实例
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define,options

define('port', default=8080, help='run port', type=int)

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(b'Tornado<br/>')  #bytes 字节
        user = {'name':'cainiao','age':18}  #字典
        print(user)
        print(repr(user))
        self.write('22<br/>33')

        self.write(user)   #字典,如果输出有个是字典,那么其他一并当做json格式输出,所以上面那个<br/>会失效显示出来,

        li = [1,2,3,4]
        import json

        li = json.dumps(li)  #列表,需要序列化成json字符
        print(li)
        print(repr(li))
        self.write(li)
        li = json.loads(li) #反序列
        print(li)
        print(repr(li))

application = tornado.web.Application(
    handlers = [
        (r'/test',TestHandler),
    ],
    debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
)


if __name__ == '__main__':
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

运行结果:
image.png

注意:上面<br/>标签失效,显示出来了,这是为什么呢?
解答:按照源码write方法解释

image.png

意思是如果给定的是字典形式,会将其转化为json格式和设置响应头为application/json格式,所以代码中几个write方法中,只有有一个为字典就都会转化!

总结:
1、write可以接受 bytes、unicode字符和字典这个三个对象;
2、如果接受的是字典,会把字典转化成 JSON 字符串,因此write也可以接受 JSON 字符串。所以对于其他的可以先转换成json格式。

缓冲区flush

write 会先把内容放在缓冲区,正常情况下,当请求处理完成后会自动把缓冲区的内容输出到浏览器,但是可以调用 flush 方法,这样可以直接把缓冲区的内容输出到浏览器,不用等待请求处理完成,这就可能先看到flush前面部分内容,后面部分内容等请求处理完才能看到。


image.png
代码实例
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define,options

define('port', default=8080, help='run port', type=int)

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(b'Tornado<br/>')  #bytes 字节
        user = {'name':'cainiao','age':18}  #字典
        print(user)
        print(repr(user))
        self.write('22<br/>33')

        self.flush()  #这样可以直接把缓冲区的内容输出到浏览器,不用等待请求处理完成,

        import time
        time.sleep(6) #通过sleep暂停几秒好验证一般write一次性全部刷到客户端去

        self.write(user)   #字典,如果输出有个是字典,那么其他一并当做json格式输出,所以上面那个<br/>会失效显示出来,


        li = [1,2,3,4]
        import json

        li = json.dumps(li)  #列表,需要序列化成json字符
        print(li)
        print(repr(li))
        self.write(li)
        li = json.loads(li) #反序列
        print(li)
        print(repr(li))

application = tornado.web.Application(
    handlers = [
        (r'/test',TestHandler),
    ],
    debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
)

if __name__ == '__main__':
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
运行结果

image.png

效果:可以在浏览器看到,刚开始输出flush前面部分,其他部分等请求处理完自动输出到浏览器中,sleep(6)休眠6秒钟主要是为了好验证看出效果。最终显示在浏览器的结果可以看出没有出现刚开始一样的<br/>原始标签,而是换行了,这是因为flush前面部分没有字典,所以响应的头部类型Content-Type:text/html;后面部分就算有字典不会再生成类型,一次请求资源只有一次生成。
如果将flush写到输出字典的后面部分

self.write(user) 
self.flush()

输出结果:


image.png

image.png

内容类型就会变成json格式。

render方式,Tornado返回一个html文件

self.render('index.html')
通过render可以返回一个 html 文件,想要 Tornado 能够正确的找到 html 文件,需要在 Application 中指定文件的位置

redirect方式,跳转路由,重定向

self.redirect(r'/index')
通过redirect可以跳转到指定的路由。

以上综合代码:

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define,options

define('port', default=8080, help='run port', type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('index.html')  #通过render可以返回一个 html 文件

class HomeHandleer(tornado.web.RequestHandler):
    def get(self):
        self.redirect(r'/index')

application = tornado.web.Application(
    handlers = [
        (r'/index',IndexHandler),
        (r'/home',HomeHandleer)
    ],
    template_path = 'templates', #想要Tornado能够正确的找到html文件,需要在 Application 中指定文件的位置
    debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
)

if __name__ == '__main__':
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

返回html文件效果:


image.png

重定向效果:


image.png

image.png
结束请求

一般程序执行完结束,一次请求结束,当调用 finish 之后,请求处理完成,类似于函数中的 return (注意:请求当中不能出现return) ,其后不能再执行 write 、render、redirect,否则会报错。


image.png

前端看不出错误,后端报错:


image.png

获取请求信息

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(self.request.remote_ip)  #客户端ip
        self.write(self.request.full_url())  #请求url地址
        print(self.request.request_time()) #访问时间
        print(self.request.uri)  #请求路由
        print(self.request.path)  #请求路由

        #继承类  tornado.web.RequestHandler 之后,可以直接调用 self.request  来获取客户端请求信息
method HTTP请求方法,例如 GET 或 POST
remote_ip 客户端的IP地址,返回值类型为字符串
full_url() 重新构建此请求的完整URL
request_time() 返回此请求执行所花费的时间
uri 请求的完整uri
path 路径部分的uri
query 查询部分的uri
vertion 请求中指定的HTTP版本,例如“HTTP / 1.1”

总结:继承类tornado.web.RequestHandler之后,可以直接调用self.request来获取客户端请求信息。

输入

代码实例
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define,options

define('port', default=8080, help='run port', type=int)


class RegisterHandler(tornado.web.RequestHandler):

    def get(self):
        info = self.get_argument('info','')
        self.write(info)
        self.render('register.html')

    def post(self, *args, **kwargs):
        name = self.get_argument('name','')
        passwd = self.get_argument('password','')

        self.write(name)
        self.write('name:'+name+'<br/>')
        self.write('password:'+passwd)


application = tornado.web.Application(
    handlers = [
        (r'/register',RegisterHandler),
    ],
    template_path = 'templates', #想要Tornado能够正确的找到html文件,需要在 Application 中指定文件的位置
    debug = True   #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
)

if __name__ == '__main__':
    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

image.png

image.png

image.png

image.png

由以上可以得出get_argumentget和post都可以获取对应参数。

  • 获取url数据,get_argument可以获取 URL (查询字符串)中的参数。
  • 获取body数据,get_argument可以获取body(请求体)中的数据。
  • get_argument返回的值始终是unicode。
其他输入了解
  • self.get_query_argument('name', 'query'),获取查询字符串中参数,即url中的。对应的也有:get_query_arguments。
  • self.get_body_argument('name', 'body'),获取 body 中的参数。对应的也有: get_body_arguments。

url传参

查询字符串风格

class RegisterHandler(tornado.web.RequestHandler):
    def get(self):
        info = self.get_argument('info','')
        self.write(info)
路由
 (r'/register',RegisterHandler)
URL

http://127.0.0.1:8000/register?info=please login at first

REST风格

handler
class LoginHandler(tornado.web.RequestHandler):
    def get(self, name, age):

        self.write('name:%s<br/>age:%s'%(name,age))
路由
(r'/login/(.+)/([0-9]+)',LoginHandler),  #正则写法,使用圆括号进行传参的时候是位置传参
(r'/login/(?P<name>.+)/(?P<age>[0-9]+)',LoginHandler) #命名组写法,使用关键字,路由与handler方法不一定顺序一致
URL
image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容