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
View Code

查看一下 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='别名'))

 

posted @ 2019-07-12 18:00  __Invoker  阅读(117)  评论(0编辑  收藏  举报