Flask -- CBV
CBV -- class base view(基于类视图)
在之前使用的函数叫视图叫做 FBV -- function base view (基于函数视图)
CBV 和 FBV 的区别 :
FBV简单, 小巧, 当不涉及到复杂的逻辑时可以使用FBV
CBV 灵活, 为什么说灵活呢, 因为, 类的封装, 继承, 多态, 你说灵活不灵活
首先,定义一个类
from flask import views # CBV需要继承view class Hello(views.MethodView): # 继承view.MethodView methods = ['get','post'] def get(self): return 'HELLO' def post(self): return 'WORLD'
现在你会发现。类有了。路由该怎么办(也就是那个@app.route的装饰器)
app.add_url_rule('/hello',view_func=Hello.as_view(name='hello'))
参数:
'/hello':访问路径
view_func=类.as_view(name='别名')
在参数中有个隐藏参数endpoint,不写默认是函数名。
name是必须写的,也是一个别名,如果endpoint没有写,别名是name对应的值
看一个完整的 CBV
from flask import Flask
form flask import view app = Flask(__name__, template_folder="templates", static_folder="static", static_url_path="/statics" ) app.secret_key = '123' class Hello(views.MethodView): methods = ['get','post'] def get(self): return 'HELLO' def post(self): return 'WORLD' app.add_url_rule('/hello',view_func=Hello.as_view(name='hello'))
基本写法有了。那么看一些这个 CBV 在源码中是什么情况
在 FBV 时。你会发现一个 @app.route()
那么 FBV 也从 route 入手 -- ctrl + 点击 route
进入源码看到这么一段代码
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop("endpoint", None) # 从options中删除endpoint,没有的话就是None
self.add_url_rule(rule, endpoint, f, **options) # 调用了 add_url_rule
return f
return decorator
进入 add_url_rule
@setupmethod def add_url_rule( self, rule, # 路径 endpoint=None, # 从 options 中取出 endpoint view_func=None, # 视图函数 provide_automatic_options=None, **options ): if endpoint is None: # endpoint如果为None endpoint = _endpoint_from_view_func(view_func) # 将试图视图函数传了进去, 返回视图函数的__name__ options['endpoint'] = endpoint # 重新赋值endpoint, 这时endpoint有可能等于视图函数的__name__, 或还是之前的值 methods = options.pop('methods', None) # 将请求方式弹出 if methods is None: methods = getattr(view_func, 'methods', None) or ('GET',) if isinstance(methods, string_types): raise TypeError('Allowed methods have to be iterables of strings, ' 'for example: @app.route(..., methods=["POST"])') methods = set(item.upper() for item in methods) required_methods = set(getattr(view_func, 'required_methods', ())) if provide_automatic_options is None: provide_automatic_options = getattr(view_func, 'provide_automatic_options', None) if provide_automatic_options is None: if 'OPTIONS' not in methods: provide_automatic_options = True required_methods.add('OPTIONS') else: provide_automatic_options = False methods |= required_methods rule = self.url_rule_class(rule, methods=methods, **options) rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule) if view_func is not None: old_func = self.view_functions.get(endpoint) if old_func is not None and old_func != view_func: raise AssertionError('View function mapping is overwriting an ' 'existing endpoint function: %s' % endpoint) self.view_functions[endpoint] = view_func # 重要的一句, 看样是是字典增加键值对的操作, key: endpoint: value: func
查看一下 as_view
@classmethod def as_view(cls, name, *class_args, **class_kwargs): def view(*args, **kwargs): self = view.view_class(*class_args, **class_kwargs) # 实例化CBV对象 return self.dispatch_request(*args, **kwargs) if cls.decorators: view.__name__ = name view.__module__ = cls.__module__ for decorator in cls.decorators: view = decorator(view) # 将参数都封装到FBV view中, 这样通过函数view的空间中就会有这些参数 view.view_class = cls view.__name__ = name view.__doc__ = cls.__doc__ view.__module__ = cls.__module__ view.methods = cls.methods view.provide_automatic_options = cls.provide_automatic_options return view # 将内部函数view返回
基本流程就是这样了。。如果搞不清的话,
记住
app.add_url_rule('路径',view_func=类.as_view(name='别名'))