CBV 写法
from flask import Flask
from flask.views import MethodViewapp = Flask(__name__)class Index(MethodView):def get(self):return 'get'def post(self):return 'post'app.add_url_rule('/index',view_func=Index.as_view(name='index'))if __name__ == '__main__':app.run()
注意:as_view( name= )中必须要写上name,并且后面跟的值不能重复,这个name 其实就是别名,最终就是fbv中的 endpoint
CBV源码分析
分析as_view的源码
传入参数:
cls=Index,name='index'
@classmethoddef as_view(cls, name, *class_args, **class_kwargs):def view(*args, **kwargs):self = view.view_class(*class_args, **class_kwargs)return self.dispatch_request(*args, **kwargs)if cls.decorators:view.__name__ = nameview.__module__ = cls.__module__for decorator in cls.decorators:view = decorator(view)view.view_class = clsview.__name__ = nameview.__doc__ = cls.__doc__view.__module__ = cls.__module__view.methods = cls.methodsview.provide_automatic_options = cls.provide_automatic_optionsreturn view
首先观察到 as_view 返回的就是 内层的函数 view,也就是说,当路由匹配成功之后就是执行内层的 view 函数
view 函数 首先将传入的视图类 实例化生成一个对象,然后执行该对象的
dispatch_request
方法该方法就类似于 Django 中的dispatch方法
重点在于传入的name参数 => view.__name__ = name
=> 其实就是将内层函数 view 的名字改成了传入的 “index”
name 必传的原因
# 由Index.as_view() ==> 如果不传
# name,Index.as_view()的执行结果就是 view 函数
由于app.add_url_rule(self, rule= ,view_func= ,... )函数的执行可知,此时传入的view_func = view, 而且此时没有传入endpoint!
'所以,该路由默认的别名就是 view 而不是视图类的名字'
'这就可能导致所有的视图类都是同一个别名--view'
所以,必须传入一个name参数
dispatch_request
源码
该方式是在MethodView 中,View 类中没有,所以如果继承了 View 类需要重写该方法
这里需要注意:只会执行视图类中跟请求方式同名的方法
def dispatch_request(self, *args, **kwargs):meth = getattr(self, request.method.lower(), None)# If the request method is HEAD and we don't have a handler for it# retry with GET.if meth is None and request.method == 'HEAD':meth = getattr(self, 'get', None)assert meth is not None, 'Unimplemented method %r' % request.methodreturn meth(*args, **kwargs)
View 类属性
CBV 书写必须继承 View 类(MethodView继承 View 类)
class View(object):methods = Noneprovide_automatic_options = Nonedecorators = ()def dispatch_request(self):raise NotImplementedError()... ...
methods
中写允许的请求方式
decorators
中写装饰给view函数
的装饰器,因为CBV本质就是执行view函数decorators元组中越靠前的,离 view函数越近,越先装饰