Tornado入门实践
tornado简介
tornado是轻量级的高性能的web应用服务器,是用python组织的代码,因此开发起来很快。它在内部采用了linux中的epoll模型和非阻塞式IO,因此对于高并发的清况能够较好的应对。这么吊的好东西,是由facebook公司出品。大公司的东西总是简洁好用。
tornado的开发其实主要需要了解三个部分,一个是路径映射,也就是相对于MVC的前端控制器,另外一个是RequestHandler,它是路径对应请求的处理器,最后是Tornado的template,它自带了模板系统,允许模板的继承,并且提供了ui_modules,可以实现控件的复用。
tornado毕竟不是专门的MVC框架,它只是一个轻量级web应用服务器,因此,没有提供完整的mvc组成部分,不过,即使这样,路径映射功能基本实现了前端控制器的功能,模板功能也非常强大,而RequestHandler 的render和render_string基本实现了视图层,所以如果不是很在意模型层,其实这已经可以作为一个MVC模型来看待了。
tornado的基本使用
了解tornado,最好从第一个application开始,以官网的例子说明:
import tornado.web
import tornado.ioloop
import tornado.escapeclass MainHandler(tornado.web.RequestHandler):
def get(self):
self.write(tornado.escape.xhtml_escape("<h1>Hello World!</h1>"))settings = {}
application = tornado.web.Application([(r'/', MainHandler),],
**settings)
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
tornado的启动通过实例化一个Application,制定了路径与handler的映射关系,然后设置监听的端口,最后通过IOLoop也就是非阻塞和epoll模型开启一个循环监听请求然后处理。这就是tornado的基本流程,接口非常简单,代码也很简短。上面就是一个简单的web系统,只不过只能返回简单的Hello world!,在后续的小节里面将降到模板系统,通过模板系统,将helloworld该成模板文件,然后再增加几个handler,一个简单的web网站就在tornado上面跑起来了。
tornado的前端控制器
从上一节的代码可以知道,tornado将路径/绑定到了MainHandler
处理器,而MainHandler
继承了基类RequestHanlder
,如果需要对更多的路径设置对应的处理器,只需要多写几个继承RequestHandler
的handler处理器即可,是不是非常方便。这里说明一下一般来说,继承RequestHandler的handler处理器只需要实现它的get
, post
, put
等方法即可,这些方法对应客户端的访问请求类型,其实一般来说这些方法都不需要其他参数了,因为在内部可以通过get_argument
或者self.request.arguments
中找到客户端的提交信息,或者请求query信息,但是,当使用一种被称作伪静态路径设置的时候,需要提取path中的信息作为query中的信息,这时候可以通过一个正则匹配的group,将这段信息捕获,被捕获的信息就会被传送给get
, post
等方法,作为它们的参数传入。例如,r'/page/([^/]+)'
将括号内捕获的字符床作为 page_id变量放到def get(self, page_id):
里面。
另外,经常要根据参数来设置一些环境变量或者改变系统设置,例如监听的端口号,是verbose模式还是normal模式,这就要使用到tornado.options
, 它其实是封装了optpase
中的OptionParser
, 可能是为了模块名的一致性,但是个人感觉OptionParser提供的接口更加丰富,而tornado.options貌似必须是key- value, 即如果你要指定服务以详细模式运行,必须要--verbose=True
这样使用,只输入了--verbose
则会抛出异常,而OptionParser则在add_option函数里面有一个action参数,可以提供默认的store_true
, store_false
, store_const
行为。
tornado的视图类
tornado与视图显示有关的函数主要有三个,这三个函数都在RequestHandler中,分别是write
, render
,render_string
。
write: 直接输出字符串内容到浏览器
render: 将制定的模板文件解析后,将解析后的html发送到浏览器,render接受参数,这些参数将作为模板中的变量使用。
render_string : 解析模板,返回解析后的字符串。
有时候利用js发送ajax请求和后台通信的时候,需要结合write
和render_string
(测试过,并且这样很灵活,出了加载模板内容还可以额外自己增加一些内容,然后write到浏览器),估计render
应该也可以,不过我没有测试。
tornado的模型系统
tornado的模型系统非常优雅,可以继承,这样要求我们不再像以前一样将整个复杂的页面用一个文件写完,庞大而臃肿,而是进行拆分,按照页面的变化情况,将共用的部分拆分出来,作为父类,一层层继承,可以大大降低代码的混乱,并且清晰易读。
语法: 将需要改变的部分,或者可以继承修改的部分用{% block block_name %}
{% end %}
两个代码块围起来,其中的部分会作为默认的内容,如果子模板继承了该部分,则该部分以子模板为准。在子模板中也是使用上述两个代码块将更新的内容围起来,不过需要在文件开头写上 {% extends "xxx.html" %}
如果某个模板文件引入的元素需要有js代码如调整显示效果,或者提交请求,则直接在该模板的末尾增加script脚本即可,即
<script src="../static/js/jquery.js"></script>
<script>
....
</script>
然而,需要注意的是模板的继承,tornado是以父模板为主模板,更新{% block block_name %}
{% end %}
围起来的内容,其他部分都以祖先模板为准,因此,有些时候我的子模板有增加的js的时候,也必须要用block包裹起来,不然模板引擎并不会将其加入到最后的解析结果中。
http://www.tornadoweb.cn/documentation