1.Tornado路由系统
1.1 Tornado程序示例
新建一个tornadodemo.py,
import tornado.ioloop import tornado.web user_info = [] class MainHandler(tornado.web.RequestHandler): # 用户get请求就执行这个方法 def get(self): # self.write("Hello, world") # 等同于Django框架里的HttpResponse方法 self.render('index.html', user_info_list = user_info) # 用户发送post请求就执行这个方法 def post(self, *args, **kwargs): # self.write('post') # self.render('index.html') # 获取用户提交的数据 user = self.get_argument('user') pwd = self.get_argument('pwd') user_info.append({'u': user, 'p': pwd}) self.redirect('/index') # 配置静态文件和html的目录;默认是在根目录下(也就是主.py文件的同级目录) settings = { 'template_path': 'template', 'static_path': 'static', } #路由系统 application = tornado.web.Application([ (r"/index", MainHandler), # 等价于django里的url.py的路由功能;用户访问index,就交给MainHandler处理。 ], **settings) if __name__ == "__main__": application.listen(8888) # epoll + socket tornado.ioloop.IOLoop.instance().start()
template/index.html,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>asdfsadf</h1> <form action="/index" method="POST"> <input type="text" name="user" /> <input type="text" name="pwd" /> <input type="submit" value="提交" /> </form> <!--<img src="/static/1.jpg">--> <hr/> <ul> # tornado模板语言,无论for或者if,结尾都是end,不像django的endfor、endif。 {% for item in user_info_list%} # tornado模板语言,取数据时跟python一模一样,如下面的取字典里的数据,可以直接dict['key'],也可以dict.get('key','default');不像django里的item.1。 <li>{{item.get('u', "123")}}-{{item['p']}}</li> {% end %} </ul> </body> </html>
这样一个使用tornado web框架的例子就做完了。
1.2 路由系统补充介绍,tornado原生支持RESTful
比如我给用户提供了查询书、购买书、取消购买书的功能,那按理说我需要给用户三个url,查询书比如说是:http://www.book.com:8888/search,购买书是:http://www.book.com:8888/buy,取消购买书是:http://www.book.com:8888/delete。用户访问不同的url进行他需要的操作。
上面仅仅是三个基本的功能,一个网站提供的功能肯定特别多,那岂不是要给用户很多个url?
那有没有更简便的方式呢,客户端和服务端进行一个约定,都只需要维护一个url就行了,比如下面这种,
# 客户端和服务端都只维护下面这一个url 书本url:http://www.book.com:8888/index # 客户端和服务端通过不同的method来执行不同的操作 method:get method:post method:delete method:put
上面的这种约定是一种软件架构方式:RESTful,双方约定好怎么获取服务和提供服务,然后只维护一个url、通过改变请求的method来通信。这也是“面向资源编程”的概念,将网络中的所有东西都视为资源。
Tornado原生支持RESTful,这也是其优势之一。
tornadodemo.py,
import tornado.ioloop import tornado.web user_info = [] class MainHandler(tornado.web.RequestHandler): # 用户以get方式访问,就执行get方法 def get(self): # self.write("Hello, world") self.render('index.html') # 用户以post方式访问,就执行post方法 def post(self, *args, **kwargs): self.write('post') # 用户以delete方式访问,就执行delete方法 def delete(self): self.write("delete") settings = { 'template_path': 'template', 'static_path': 'static', } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) # epoll + socket tornado.ioloop.IOLoop.instance().start()
1.3 tornado原生支持二级域名
class MainHandler(tornado.web.RequestHandler): def get(self): self.write("www") class CmdbMainHandler(tornado.web.RequestHandler): def get(self): self.write("cmdb") settings = { 'template_path': 'template', 'static_path': 'static', } # 默认二级域名是www;用户输入www.zsc.com:8888/index时,执行MainHandler里的方法。 application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) # 用户输入的域名是cmdb.zsc.com:8888/index时,执行CmdbMainHandler里的方法。 application.add_handlers("cmdb.zsc.com",[ (r"/index", CmdbMainHandler), ], **settings) # django里就是www.zsc.com:8000/index、www.zsc.com:8000/cmdb这样。
2. Tornado模版语言
2.1 引入模板语言
# 给前端返回一个li列表 class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html',li=[1,2,3,4]) # index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> # tornado里使用模板语言会更像python,如下面的可以直接使用len()和range()方法,在循环里也可以用break和continue。 {% for i in range(len(li)) %} <p> {{ i }} -- {{ li[i] }} </p> {% break%} {% end %} <hr/> </body> </html>
2.2 母板的使用
tornado里使用模板与django类似,只是django里是{% block one %} {% endblock %},tornado里是{% block one %} {% end %}。
2.3
2.3.1 ui_methods
第一步,在项目app.py同级目录下(不一定非得建在app.py同级目录下,只是一会import的时候省的写长目录了)新建一个python模块,比如叫test_ui_methods.py,内容见下,
def gotest(self,a): return "10"
第二部,app.py,
import tornado.ioloop import tornado.web user_info = [] class MainHandler(tornado.web.RequestHandler): def get(self): # self.write("Hello, world") self.render('index.html',li=[1,2,3,4]) def post(self, *args, **kwargs): self.write('post') def delete(self): self.write("delete") # 引入这个模块,并设置路径 import test_ui_methods settings = { 'template_path': 'template', 'static_path': 'static', 'ui_methods':test_ui_methods, } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) # epoll + socket tornado.ioloop.IOLoop.instance().start()
template/index.html,
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> # 引用这个ui_methods {{ gotest('1') }} {% for i in range(len(li)) %} <p> {{ i }} -- {{ li[i] }} </p> {% continue %} {% end %} <hr/> </body> </html>
配置完毕后,用户访问http://127.0.0.1:8888/index就会看到网页上“{{ gotest('1') }}”对应的位置显示了10。
2.3.2 ui_modules
ui_modules与ui_methods类似。
app.py,
import test_ui_methods #导入ui_modules import test_ui_modules settings = { 'template_path': 'template', 'static_path': 'static', 'ui_methods':test_ui_methods, 'ui_modules':test_ui_modules, }
新建test_ui_modules.py,
from tornado.web import UIModule class custom(UIModule): def render(self,*args,**kwargs): return '<h1>UIMODULES</h1>'
index.html,
<body> {{ gotest('1') }} # 引入ui_modules {% module custom() %} {% for i in range(len(li)) %} <p> {{ i }} -- {{ li[i] }} </p> {% continue %} {% end %} <hr/> </body>
2.3.2 ui_modules的功能介绍
ui_modules不仅能插入html代码,还可以插入js、css,如下是解释,
class custom(UIModule): def render(self,*args,**kwargs): return escape.xhtml_escape('<h1>UIMODULES</h1>') # 在</body>前面插入一个<script src="http://jsone.js" type="text/javascript"></script>和<script src="http://jstwo.js" type="text/javascript"></script> def javascript_files(self): return ['http://jsone.js','http://jstwo.js'] # 在</body>前面插入一个<script> function f1(){alert(123);} f1();</script>,即定义了一个函数并调用它。 def embedded_javascript(self): return "function f1(){alert(123);} f1();" # 在前端html加入一个css文件 def css_files(self): pass # 在前端html插入一段css代码 def embedded_css(self): pass