Flask源码之实例化flask对象

flask中首先我们需要实例化一个Flask对象,而这个Flask对象进行了大量的封装。我们去掉一些不必要的内容,然后进行简单分析,随着分析的深入,后面会对前面内容进行更新,说明。

class Flask():
    # 静态字段
    request_class = Request
    response_class = Response
    config_class = Config
    url_rule_class = Rule
    url_map_class = Map
    template_folder = None

    def __init__(self,
                 static_url_path=None,
                 static_folder="static",
                 template_folder="templates",
                 ):
        self.static_url_path = static_url_path
        self.static_folder = static_folder
        self.view_functions = {}
        self.before_request_funcs = {}
        self.before_first_request_funcs = []
        self.after_request_funcs = {}
        self.blueprints = {}
        self.url_map = self.url_map_class()
        if self.has_static_folder:
            self.add_url_rule(
                self.static_url_path + "/<path:filename>",
                endpoint="static",
                host=static_host,
                view_func=self.send_static_file,
            )

从Django的经验来看,静态字段,分别为请求,响应,配置,路由,模板文件。

self.static_url_path = static_url_path指定静态文件的路由

self.static_folder = static_folder 则是静态文件的文件夹,下面有一个判断:

if self.has_static_folder:
            self.add_url_rule(
                self.static_url_path + "/<path:filename>",
                endpoint="static",
                host=static_host,
                view_func=self.send_static_file,
            )

has_static_folder方法判断是否指定了static_folder,如果没有返回False,否则返回True.

 @property
    def has_static_folder(self):
        return self.static_folder is not None

如果指定了static_folder,那么意味着需要为静态文件指定Url(如果没有静态文件夹,当然也没必要指定url)

然后调用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)

        # if the methods are not given and the view_func object knows its
        # methods we can use that instead.  If neither exists, we go with
        # a tuple of only ``GET`` as default.
        if methods is None:
            methods = getattr(view_func, "methods", None) or ("GET",)
        methods = set(item.upper() for item in methods)

        # Methods that should always be added
        required_methods = set(getattr(view_func, "required_methods", ()))

        # Add the required methods now.
        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

首先判断别名,如果没指定别名,别名被设定为函数名,然后将别名保存在options中。

接着是方法:先从Options中获取别名,如果没有,则得到None,即没有指定方法,那么methods被设置为GET,然后将方法名变成大写

再接着是rule, 即url, 通过url被 rule = self.url_rule_class(rule, methods=methods, **options)用来实例化一个url_rule_class=Rule对象,接着这个rule对象被 url_map=Map调用add方法封装成了Map对象。

最后去view_func中获取当前endpoint对应的视图函数,如果视图函数与当前函数名不同则报错,如果没有endpoint就添加当前endpoint与函数对应的关系到view_func字典中。

 

上面就是实例化Flask对象阶段所做的事情,简单总结一下:

指定很多静态属性,及其它属性。

指定静态文件的文件夹,并为它指定路由,在些过程中指定了请求方法,建立url与视图函数的对应关系。

 

上一篇:Flask 源码之Local, LocalStack

下一篇:Flask源码分析之请求流程