flask-analysis
  • 简介
  • 序
  • 代码目录与详解
    • artwork目录
    • docs目录
    • examples目录
    • tests目录
    • 其他辅助文件
  • 主程序剖析
    • 短短几行 flask到底做了啥
    • 路由系统 为何如此简洁高效
    • 路由匹配探秘
    • 全局对象request解析
    • 全局对象g解析
    • 全局对象current_app解析
    • 全局对象session解析
    • flask特性之signal系统
    • flask特性之blueprint
    • flask特性之methodview
    • flask特性之配置系统
    • flask特性之模板系统
  • flask生态
    • 官方文档
    • 扩展推荐
    • 扩展开发
  • 推荐阅读
  • 贡献名单
Powered by GitBook
On this page

Was this helpful?

  1. 主程序剖析

flask特性之methodview

大型项目中,代码不仅仅是功能的实现,更主要在于代码的可维护性、可读性以及良好的代码组织结构。为了实现这些特性,methodview和blueprint就是flask的两大利器。blueprint在之前的文章为们已经分析完毕,接下来看看methodview的魅力。

methodview使用示例:

from flask.views import MethodView

class CounterAPI(MethodView):
    def get(self):
        return session.get('counter', 0)

    def post(self):
        session['counter'] = session.get('counter', 0) + 1
        return 'OK'

app.add_url_rule('/counter', view_func=CounterAPI.as_view('counter'))

methodview在使用时,路由的逻辑和app.route是一致的,关键在于MethodView类的as_view方法,那它是如何实现的呢?

MethodView的实现:

class View(object):

    methods = None

    provide_automatic_options = None

    decorators = ()

    def dispatch_request(self):
        """Subclasses have to override this method to implement the
        actual view function code.  This method is called with all
        the arguments from the URL rule.
        """
        raise NotImplementedError()

    @classmethod
    def 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__ = name
            view.__module__ = cls.__module__
            for decorator in cls.decorators:
                view = decorator(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

class MethodView(with_metaclass(MethodViewType, 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.method
        return meth(*args, **kwargs)

可以看到MethodView类的as_view是集成自父类View,可以看到as_view被装饰成classmethod,as_view内部定义view函数,并将其返回来充当url对应的view_func,我们详细看一下view函数本身处理的逻辑,也就是当请求到达时,view函数的处理过程。简单来看就是self是view.view_class的实例化对象,而后把请求相关参数传递给self.dispatch_request,处理请求,最后返回。在View类中as_view函数中,我们可以看到在内部函数view返回时,对view函数的本身的属性进行了修改,包括view_class、__doc__、__module__、methods.provide_automatic_options。这都是在添加路由映射时app.add_url_rule所需的关键信息。

在View类中,我们可以看到一个decorators属性,从名称上看,这是装饰器列表,我们可以提供自己的装饰器,在修改view函数的运行时行为,做到程序高内聚,低耦合。

Previousflask特性之blueprintNextflask特性之配置系统

Last updated 5 years ago

Was this helpful?