2019独角兽企业重金招聘Python工程师标准>>>
即插视图;
说明: FLASK的视图灵感来自于DJANGO的基于类而非基于函数的通用视图,主要目的是为了解决多个视图函数之间已经实现的部分,通过类继承的方式继承到其它视图,总之为了一点,就是少写代码,然后通过add_url_rule让我们定义的视图类支持动态插入,也就是所谓的即插视图
深入视图:
# 转换前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template # 说明: 导入其它模块 app = Flask(__name__) @app .route( '/about' ) def web_about(): return render_template( '/web/about.html' ) @app .route( '/usr_manager' ) def usr_manager(): usrs = [u '李满满' ] return render_template( 'web/usr/manager.html' , usrs = usrs) @app .route( '/grp_manager' ) def grp_managr(): grps = [u '管理员' ] return render_template( 'web/grp/manager.html' , grps = grps) if __name__ = = '__main__' : app.run(host = '0.0.0.0' , port = 9000 , debug = True ) |
说明: 如上三个视图函数代码基本类似,都是获取数据渲染模版或直接渲染模版,我们可以尝试通过即插视图子类继承来让适应于更多的模型和模版,更加的灵活,首先得转换为类视图
# 转换后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template, jsonify from flask.views import View # 说明: 导入其它模块 app = Flask(__name__) class BaseView(View): def __init__( self , template_name): self .template_name = template_name def get_objects( self ): return {} def render_template( self , context): return render_template( self .template_name, * * context) def dispatch_request( self ): context = { 'objects' : self .get_objects()} return self .render_template(context) class UsrManager(BaseView): def get_objects( self ): return [u '李满满' ] class GrpManager(BaseView): def get_objects( self ): return [u '管理员' ] app = Flask(__name__) app.add_url_rule( '/about' , view_func = BaseView.as_view( 'web_about' , template_name = 'web/about.html' )) app.add_url_rule( '/web/usr/manager' , view_func = UsrManager.as_view( 'usr_manager' , template_name = 'web/usr/manager.html' )) app.add_url_rule( '/web/grp/manager' , view_func = GrpManager.as_view( 'grp_manager' , template_name = 'web/grp/manager.html' )) @app .route( '/' ) def index(): return jsonify({ 'all_url_map' : app.url_map.__str__()}) if __name__ = = '__main__' : app.run(host = '0.0.0.0' , port = 9000 , debug = True ) |
说明: 使用基于类的即插视图首先得声明一个继承自flask.views.View的子类,且必须实现一个dispatch_request调度请求的方法,在调度请求中返回原始响应数据即可,如果要将其加入app.url_map表中需要通过app.add_url_rule(self, *args, **kwargs)方法将URL规则与视图函数绑定, 既然绑定的是视图函数,那肯定不能直接绑定子类,基类flask.views.View为我们提供了一个.as_view(name, *args, **kwargs)类方法,继承下来我们可以直接调用生成一个名字为name的视图函数,当请求符合URL规则时会通过转换器将to_python数据按照app.url_map传递给对应的视图函数来处理,视图函数有可能是被装饰的函数,也有可能是通过即插视图生成的函数,最终返回的结果在在响应装饰器中修饰以便最终返回给客户端
扩展: 如果想限制HTTP方法,可以直接在基类BaseView或是子类中声明类属性methods=['GET', 'POST']或是指定单GET/POST协议即可,如果希望对于GET/POST协议做单独处理,只需要基类继承flask.views.MethodView然后在子类中实现get/post方法,然后就可以不提供methods类属性,它会自动的按照子类中的定义去处理GET或是POST请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template, jsonify, request from flask.views import MethodView # 说明: 导入其它模块 app = Flask(__name__) class BaseView(MethodView): def __init__( self , template_name): self .template_name = template_name def render_template( self , context): return render_template( self .template_name, * * context) def dispatch_request( self ): objects = getattr ( self , request.method.lower())() context = { 'objects' : objects} return self .render_template(context) class UsrManager(BaseView): def get( self ): return [u '李满满' ] def post( self ): return [u '刘珍珍' ] class GrpManager(BaseView, MethodView): def get( self ): return [u '匿名者' ] def post( self ): return [u '管理员' ] app = Flask(__name__) app.add_url_rule( '/about' , view_func = BaseView.as_view( 'web_about' , template_name = 'web/about.html' )) app.add_url_rule( '/web/usr/manager' , view_func = UsrManager.as_view( 'usr_manager' , template_name = 'web/usr/manager.html' )) app.add_url_rule( '/web/grp/manager' , view_func = GrpManager.as_view( 'grp_manager' , template_name = 'web/grp/manager.html' )) @app .route( '/' ) def index(): return jsonify( help (app.add_url_rule)) if __name__ = = '__main__' : app.run(host = '0.0.0.0' , port = 9000 , debug = True ) |
扩展: FLASK还支持在运行视图函数之前通过装饰器的方式来实现权限检查,登录验证等操作,由于视图类最终是通过.as_view生成视图函数,所以基于视图类添加修饰器无卵用,只能在.as_view上做,新版的直接支持基类属性decorators列表,定义装饰器列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template, jsonify, request, session, abort from flask.views import MethodView # 说明: 导入其它模块 app = Flask(__name__) def user_required(func): def wrapper( * args, * * kwargs): uid = session.get( 'id' , None ) if not uid: abort( 401 ) return func( * args, * * kwargs) return wrapper class BaseView(MethodView): decorators = [user_required] def __init__( self , template_name): self .template_name = template_name def render_template( self , context): return render_template( self .template_name, * * context) def dispatch_request( self ): objects = getattr ( self , request.method.lower())() context = { 'objects' : objects} return self .render_template(context) class UsrManager(BaseView): def get( self ): return [u '李满满' ] def post( self ): return [u '刘珍珍' ] class GrpManager(BaseView, MethodView): def get( self ): return [u '匿名者' ] def post( self ): return [u '管理员' ] app = Flask(__name__) app.add_url_rule( '/about' , view_func = BaseView.as_view( 'web_about' , template_name = 'web/about.html' )) app.add_url_rule( '/web/usr/manager' , view_func = UsrManager.as_view( 'usr_manager' , template_name = 'web/usr/manager.html' )) app.add_url_rule( '/web/grp/manager' , view_func = GrpManager.as_view( 'grp_manager' , template_name = 'web/grp/manager.html' )) @app .route( '/' ) def index(): return jsonify( help (app.add_url_rule)) if __name__ = = '__main__' : app.run(host = '0.0.0.0' , port = 9000 , debug = True ) |
说明: FLASK为我们提供了decorators类属性来设置装饰器列表,当然其实也可以手动的在app.add_url_rule之前来修饰view_func = user_required(BaseView.as_view('web_about', template_name='web/about.html')),此时view_func就已被修饰,添加了验证功能
登录乐搏学院官网http://www.learnbo.com/
或关注我们的官方微博微信,还有更多惊喜哦~
本文出自 “满满李 - 运维开发之路” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1866526