Flask中的CBV

Flask中的CBV

在Flask中和Django一样有两种视图模式,一种是基于函数,一种是基于类。下面来讨论一下Flask的CBV模式。

首先,说明一下flask视图函数注册路由的本质:
其实,route装饰器内部也是通过调用add_url_rule()方法实现的路由注册,只是route装饰器看起来更加美观

源码的route函数,如下

def route(self, rule, **options):

	        def decorator(f):
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f

        return decorator

下面我们来看一下CBV的书写方式:

class Login(views.MethodView):
    def get(self):
    
        return "hello"

app.add_url_rule("/",view_func=Login.as_view("login"))
#view_func是add_url_rule(rule, endpoint, f, **options),的第三个参数f

要使用定义的视图类,必须要继承了MethodView,这个类继承了View类和MethodViewType类,内部封装了我们需要的功能

class MethodView(with_metaclass(MethodViewType, View)):

下面我们看一下as_view方法,

    def as_view(cls, name, *class_args, **class_kwargs):
        """Converts the class into an actual view function that can be used
        with the routing system.  Internally this generates a function on the
        fly which will instantiate the :class:`View` on each request and call
        the :meth:`dispatch_request` method on it.

        The arguments passed to :meth:`as_view` are forwarded to the
        constructor of the class.
        """

        def view(*args, **kwargs):
            self = view.view_class(*class_args, **class_kwargs)
            return self.dispatch_request(*args, **kwargs)

        if cls.decorators:
            view.__name__ = name
            view.__module__ = cls.__module__
            for decorator in cls.decorators:
                view = decorator(view)

        # We attach the view class to the view function for two reasons:
        # first of all it allows us to easily figure out what class-based
        # view this thing came from, secondly it's also used for instantiating
        # the view class so you can actually replace it with something else
        # for testing purposes and debugging.
        view.view_class = cls
        view.__name__ = name   #view.__name__ = "login"
        #view是上面定义的函数,函数名.__name__就是这个函数的函数名,
        #这里我们就当于重新赋值了view这个函数的函数名
        view.__doc__ = cls.__doc__
        view.__module__ = cls.__module__
        view.methods = cls.methods
        view.provide_automatic_options = cls.provide_automatic_options
        return view   

经过上面对as_view的分析,我们知道,as_view返回了一个名字叫login的函数,然后开始进入add_url_rule方法,

 def add_url_rule(
        self,
        rule,
        endpoint=None,
        view_func=None,
        provide_automatic_options=None,
        **options
    ):


        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options["endpoint"] = endpoint
        methods = options.pop("methods", None)

刚开始endpoint为空,所以,进入if条件,执行_endpoint_from_view_func,

def _endpoint_from_view_func(view_func):
    """Internal helper that returns the default endpoint for a given
    function.  This always is the function name.
    """
    assert view_func is not None, "expected view func if endpoint is not provided."
    return view_func.__name__

我们看到_endpoint_from_view_func返回了函数的名字,执行if条件内的语句后,
就得到了,endpoint=函数名,所以endpoint和view_func=Login.as_view(“login”)中的login名字是一样的。

总结来说,Flask的CBV本质上和FBV是一样的,都是执行add_url_rule方法,主要就是使用形式上的不同

个人理解如上,如有错误欢迎指出,一定改正,共勉。

参考文章:https://blog.csdn.net/m0_37519490/article/details/80608365

你可能感兴趣的:(Flask,flask的CBV浅谈)