Flask即插视图与tornado比较
由于公司使用了Tornado框架和Flask框架,之前一直使用的都是Flask框架,已经对url下面紧跟着视图的写法很固执。刚开始接触Tornado框架,对于其url和视图分开的写法思想上无法转变。今天看了Flask的源码和相关教程看到原来 Flask也可以写出和Tornado类似的代码结构--Flask即插视图。
代码如下:
from functools import wraps from flask import Flask, request from flask.views import MethodView app = Flask(__name__) # get请求装饰器 def decorator_func_get(f): @wraps(f) def write(*args, **kwargs): print(request.method, 'decorator_func_get') print('You can add some decorator before request into view function!') return f(*args, **kwargs) return write # post请求装饰器 def decorator_func_post(f): @wraps(f) def write(*args, **kwargs): print(request.method, 'decorator_func_post') print('You can add some decorator before request into view function!') return f(*args, **kwargs) return write # 公用装饰器 def decorator_func_all(f): @wraps(f) def write(*args, **kwargs): print(request.method, 'decorator_func_all') print('You can add some decorator before request into view function!') return f(*args, **kwargs) return write class User(MethodView): # 所以http方法进入后都要使用的装饰器 decorators = [decorator_func_all] # 只针对get请求的装饰器 @decorator_func_get def get(self, user_id): return f'get uid:{user_id}' # 只针对post请求的装饰器 @decorator_func_post def post(self): uid = request.form.get('user_id') return f'create a user {uid}' def delete(self, user_id): return f'delete a uid:{user_id}' def put(self, user_id): return f'update a uid:{user_id}' # 可以重构一个路由注册函数,可以更加方便 user_view = User.as_view('user_api') # 'user_api'为endpoint app.add_url_rule('/users', defaults={'user_id': None}, view_func=user_view, methods=['GET']) # url:/users,GET app.add_url_rule('/users', view_func=user_view, methods=['POST']) # url:users,POST app.add_url_rule('/users/<int:user_id>', view_func=user_view, methods=['GET', 'PUT', 'DELETE']) # url:users,POST app.run(host='127.0.0.1', port=8000, debug=True)
其实对于即插视图的add_url_rule()方法和如下的route()方法都是一样的,因为源码中,route()调用的就是add_url_rule()方法。
代码段:1
@app.route('/', methods=['GET', 'POST'])
@some_decorator def index(): data = { 'msg': 'API SERVER IS RUNNING~', 'version': version, } data.update(get_version_ctrl()) return msg(data)
即插视图优点:
- 可以更好的理解tornado框架的大致框架结构。
- 写出更容易符合RestFul风格的代码,因为对于资源的增删改查,通过get,post等方法对应到相关的类方法上。
- 不用像 代码段:1 中那样,在GET,POST都存在时,使用
if request.method=='GET': print('do some get method things') else: print('do some other method things')
如此费事恶心的代码
- 解耦代码,不用像 代码段:1 中那样装饰器只能对整个视图函数使用,无法具体到对应的不同的请求方法上。
- 路由集中管理
Tornado框架简单程序(主要体现其注册视图函数的方法和flask的即插视图很像):
import torndb import tornado.web import tornado.ioloop from tornado.options import define,options,parse_command_line define('port',default=8888,help='run on the port',type=int) database=torndb.Connection('localhost','talk',user='root',password='ll') l=[] class MainHandler(tornado.web.RequestHandler): def get(self): self.render('a.html',title='haha',items=l) def post(self): count=1 print(self.request.remote_ip) talk=self.get_argument('talk') talk=str(talk) database.execute('insert into chatting(id,content) values(%d,"%s")'%(count,talk)) l.append(talk) self.render('a.html',title='haha',items=l) def main(): parse_command_line() app=tornado.web.Application( [ (r'/',MainHandler), ], ) app.listen(options.port) tornado.ioloop.IOLoop.instance().start() if __name__=='__main__': main()