tornado框架之基本用法

发布时间 2023-12-08 15:12:30作者: 木屐呀

Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。

Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题,请参阅 C10K problem。)

安装

1 pip install tornado
2 源码安装
3 https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz

一、快速上手

 1 import tornado.ioloop
 2 import tornado.web
 3 
 4 class MainHandler(tornado.web.RequestHandler):
 5     def get(self):
 6         self.write('hello world')
 7 
 8 application = tornado.web.Application([
 9     (r'/',MainHandler),
10 ])
11 
12 if __name__ == '__main__':
13     application.listen(8888)
14     tornado.ioloop.IOLoop.instance().start()

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

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

第三步:服务器接受请求,并交由对应的类处理该请求

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

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

二、路由系统

路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类

 1 import tornado.ioloop
 2 import tornado.web
 3 
 4 class MainHandler(tornado.web.RequestHandler):
 5     def get(self):
 6         self.write("Hello, world")
 7 
 8 
 9 class StoryHandler(tornado.web.RequestHandler):
10     def get(self, story_id):
11         self.write("You requested the story " + story_id)
12 
13 
14 class BuyHandler(tornado.web.RequestHandler):
15     def get(self):
16         self.write("buy.wupeiqi.com/index")
17 
18 
19 application = tornado.web.Application([
20     (r"/", MainHandler),
21     (r"/story/([0-9]+)", StoryHandler),
22 ])
23 
24 application.add_handlers('buy.laosiji.com$', [
25     (r'/index', BuyHandler),
26 ])
27 
28 if __name__ == "__main__":
29     application.listen(8888)
30     tornado.ioloop.IOLoop.instance().start()

三、模板

Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者

 1 ##模板引擎渲染原理
 2 
 3 li = []
 4 
 5 li[0] = """
 6 <!DOCTYPE html>
 7 <html lang="en">
 8 <head>
 9     <meta charset="UTF-8">
10     <title>Title</title>
11 </head>
12 <body>
13     <h1>Welcome to Tornado</h1>
14     <form action="/login.html" method="post">
15         <input type="text" name="username" placeholder="用户名">
16         <input type="password" name="password" placeholder="用户密码">
17         <input type="submit" value="提交">
18 
19 """
20 
21 li[1] = "用户名或密码错误" #根据msg,传过来对应值
22 {{ msg }}
23 
24 li[2] = """
25     </form>
26 </body>
27 </html>
28 """
29 
30 结果 = "".join(li)
模板引擎渲染原理

 Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}

控制语句和对应的 Python 语句的格式基本完全相同。我们支持 ifforwhile 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <div class="pg-header">
 9         <a href="#">girls</a>
10     </div>
11     {% block RenderBody %}{% end %}
12 </body>
13 </html>
layout.html
 1 {% extends 'layout.html' %}
 2 
 3 {% block RenderBody %}
 4     <h1>Index</h1>
 5     <ul>
 6         {% for item in li %}
 7             <li>{{ item }}</li>
 8         {% end %}
 9     </ul>
10 {% end %}
index.html
 1 import tornado.ioloop
 2 import tornado.web
 3 
 4 
 5 class MainHandler(tornado.web.RequestHandler):
 6     def get(self):
 7         self.render('home/index.html',li="girls")
 8 
 9 settings = {
10     'template_path':'views'
11 }
12 
13 
14 application = tornado.web.Application([
15     (r"/", MainHandler),
16 ],**settings)
17 
18 
19 if __name__ == "__main__":
20     application.listen(8888)
21     tornado.ioloop.IOLoop.instance().start()
tornado_test.py

在模板中默认提供了一些函数、字段、类以供模板使用:

  • scapetornado.escape.xhtml_escape 的別名
  • xhtml_escapetornado.escape.xhtml_escape 的別名
  • url_escapetornado.escape.url_escape 的別名
  • json_encodetornado.escape.json_encode 的別名
  • squeezetornado.escape.squeeze 的別名
  • linkifytornado.escape.linkify 的別名
  • datetime: Python 的 datetime 模组
  • handler: 当前的 RequestHandler 对象
  • requesthandler.request 的別名
  • current_userhandler.current_user 的別名
  • localehandler.locale 的別名
  • _handler.locale.translate 的別名
  • static_url: for handler.static_url 的別名
  • xsrf_form_htmlhandler.xsrf_form_html 的別名

Tornado默认提供的这些功能其实本质上就是 UIMethod 和 UIModule,我们也可以自定义从而实现类似于Django的simple_tag的功能:

1、定义

1 def tab(request,val):
2     print(request,val) #(<__main__.MainHandler object at 0x0000000003D15748>, 11)
3     return '<a>UIMethod<a>'  #若想显示html格式,需在setting设置autoescape以及模板中机上raw
4     # return '<a>UIMethod<a>' #这样渲染不出来
5     # return 'UIMethod'
uimethods.py
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 from tornado.web import UIModule
 5 from tornado import escape
 6 
 7 class Custom(UIModule):
 8     def css_files(self):
 9         return "sfs"  #引入css静态文件
10 
11     def embedded_css(self):
12         return ".c1{display:none}"  #嵌入css
13 
14     def javascript_files(self):
15         return "js" #引入javascript静态文件
16 
17     def embedded_javascript(self):
18         return "function f1(){alert(123);}"   #生成javascript
19 
20     def render_string(self, path, **kwargs):
21         print(path)
22         return "fsgs"
23 
24     def render(self, *args, **kwargs):
25         print(self,args,kwargs) #(<uimodules.Custom object at 0x0000000003D3F4E0>, (22,), {})
26         return "<h1>UIModule</h1>"  #默认不进行转译,直接显示html格式
27         # return escape.xhtml_escape('<h1>UIModule</h1>')  ->>进行转译,不显示html格式
uimodules.py

2、注册

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import tornado.ioloop
 5 import tornado.web
 6 import uimodules as md
 7 import uimethods as mt
 8 
 9 class MainHandler(tornado.web.RequestHandler):
10     def get(self):
11         self.render('home/index.html',li="girls")
12 
13 settings = {
14     'template_path':'views',
15     'static_path':'static',
16     'ui_methods':mt,#UIMethod注册
17     'ui_modules': md, #UIModule注册
18     'autoescape':None,#不将tab返回的字符串进行转译(阻止HTML格式渲染)
19 }
20 
21 
22 application = tornado.web.Application([
23     (r"/", MainHandler),
24 ],**settings)
25 
26 
27 if __name__ == "__main__":
28     application.listen(8888)
29     tornado.ioloop.IOLoop.instance().start()
tornado_test.py

3、使用

 1 {% extends 'layout.html' %}
 2 
 3 {% block RenderBody %}
 4     <h1>Index</h1>
 5     <ul>
 6         {% for item in li %}
 7             <li>{{ item }}</li>
 8         {% end %}
 9     </ul>
10     {{ tab(11) }}
11     {% module Custom(22) %}
12 {% end %}
index.html

总结:

 1 Tornado
 2 1.基本操作
 3     -路由系统
 4         -url -类(根据method执行方法)
 5     -控制器
 6         class Foo(xxxx):
 7             def get(self):
 8             self.render()
 9             self.write()
10             self.redirect()
11             self.get_argument()
12             self.get_arguments()
13             self.get_cookie()
14             self.set_cookie()
15             
16             self.set_secure_cookie('is_login','true') #加密cookie
17             is_login = self.get_secure_cookie('is_login') #获取加密cookie字符串
18             #加密cookie时配置文件设置
19             settings = {
20                 # Exception: You must define the 'cookie_secret' setting in your application to use secure cookies
21                 'cookie_secret':'fsgfgdrhrthrthryryty'
22             }
23             
24             self.request.files['abc'] #获取提交文件
25             self._headers  #获取请求头
26             
27             self.request 对象  -》from tornado.httpserver import HTTPRequest #查看
28             
29                 pass
30             def post(self):
31                 pass
32     -模板引擎(更接近python)
33         -基本
34             {{ li[0] }}
35             {% for i in range(10) %}
36             {% end %}
37         -UIMethod 在模板中自定义方法(类似django的simple_tag)
38             -内容
39         -UIModule 在模板中自定义方法(类似django的simple_tag)
40             -内容
41             -CSS JS