Flask之Blueprint

来源:互联网 发布:网站程序和网站源码 编辑:程序博客网 时间:2024/05/25 01:35

Blueprint

Blueprint继承自_PackageBoundObject类

class Blueprint(_PackageBoundObject):    warn_on_modifications = False    _got_registered_once = False    def __init__(self, name, import_name, static_folder=None,                 static_url_path=None, template_folder=None,                 url_prefix=None, subdomain=None, url_defaults=None,                 root_path=None):        _PackageBoundObject.__init__(self, import_name, template_folder,                                     root_path=root_path)        self.name = name        self.url_prefix = url_prefix        self.subdomain = subdomain        self.static_folder = static_folder        self.static_url_path = static_url_path        self.deferred_functions = []        if url_defaults is None:            url_defaults = {}        self.url_values_defaults = url_defaults

除了Blueprint名称和导入的模块名,其他参数都有默认值,因此Blueprint可以这样初始化:

# -*- coding: utf-8 -*-from flask import Blueprintauth = Blueprint("auth", __name__)import views


Blueprint实例创建之后,需要调用Flask.register_blueprint()进行注册,我们来分析这个函数的处理流程:

    def register_blueprint(self, blueprint, **options):        """Registers a blueprint on the application.        .. versionadded:: 0.7        """        first_registration = False        if blueprint.name in self.blueprints:            assert self.blueprints[blueprint.name] is blueprint, \                'A blueprint\'s name collision occurred between %r and ' \                '%r.  Both share the same name "%s".  Blueprints that ' \                'are created on the fly need unique names.' % \                (blueprint, self.blueprints[blueprint.name], blueprint.name)        else:            self.blueprints[blueprint.name] = blueprint            self._blueprint_order.append(blueprint)            first_registration = True        blueprint.register(self, options, first_registration)
Flask有个列表blueprints,里面保存了所有Blueprint名,注册新的Blueprint时,首先以Blueprint为索引检查Flask列表blueprints,如果存在了,则给出告警;否则,将该Blueprint名称保存到列表blueprjints中,并调用Blueprint.register()进行深入注册。

继续分析Blueprint.register()处理流程:

    def register(self, app, options, first_registration=False):        """Called by :meth:`Flask.register_blueprint` to register a blueprint        on the application.  This can be overridden to customize the register        behavior.  Keyword arguments from        :func:`~flask.Flask.register_blueprint` are directly forwarded to this        method in the `options` dictionary.        """        self._got_registered_once = True        state = self.make_setup_state(app, options, first_registration)        if self.has_static_folder:            state.add_url_rule(self.static_url_path + '/<path:filename>',                               view_func=self.send_static_file,                               endpoint='static')        for deferred in self.deferred_functions:            deferred(state)
如果Blueprint有自己的static目录,则把static目录也添加到Flask路由规则中



BlueprintSetupState

这个类是Blueprint和Flask类之间的临时粘合剂。对象变量分别有Blueprint和Flask的引用、可选参数、url前缀等。需要注意的是,这里的可选参数是一般是调用Flask.register_blueprint()时传入的,优先级要高于Blueprint的可选参数

class BlueprintSetupState(object):    """Temporary holder object for registering a blueprint with the    application.  An instance of this class is created by the    :meth:`~flask.Blueprint.make_setup_state` method and later passed    to all register callback functions.    """    def __init__(self, blueprint, app, options, first_registration):        #: a reference to the current application        self.app = app        #: a reference to the blueprint that created this setup state.        self.blueprint = blueprint        #: a dictionary with all options that were passed to the        #: :meth:`~flask.Flask.register_blueprint` method.        self.options = options        self.first_registration = first_registration        subdomain = self.options.get('subdomain')        if subdomain is None:            subdomain = self.blueprint.subdomain        self.subdomain = subdomain        url_prefix = self.options.get('url_prefix')        if url_prefix is None:            url_prefix = self.blueprint.url_prefix        #: The prefix that should be used for all URLs defined on the        #: blueprint.        self.url_prefix = url_prefix        #: A dictionary with URL defaults that is added to each and every        #: URL that was defined with the blueprint.        self.url_defaults = dict(self.blueprint.url_values_defaults)        self.url_defaults.update(self.options.get('url_defaults', ()))    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):        """A helper method to register a rule (and optionally a view function)        to the application.  The endpoint is automatically prefixed with the        blueprint's name.        """        if self.url_prefix:            rule = self.url_prefix + rule        options.setdefault('subdomain', self.subdomain)        if endpoint is None:            endpoint = _endpoint_from_view_func(view_func)        defaults = self.url_defaults        if 'defaults' in options:            defaults = dict(defaults, **options.pop('defaults'))        self.app.add_url_rule(rule, '%s.%s' % (self.blueprint.name, endpoint),                              view_func, defaults=defaults, **options)

初始化有几个地方需要注意(下面的可选参数都是调用Flask.register_blueprint()时传进来的):

  • 如果可选参数中存在"url_prefix",则以可选参数为准,否则以Blueprint自带的"url_prefix"为准
  • 如果可选参数中存在"subdomain",则以可选参数为准,否则以Blueprint自带的"subdomain"为准


BlueprintSetupState唯一对外提供的方法是 def add_url_rule(self, rule, endpoint=None, view_func=None, **options),该方法对url做些处理后,最终还是调用Flask的add_url_rule()来添加路由规则。这里我们之间查看Flask.add_url_rule()方法如何处理的:

class Flask(_PackageBoundObject):    @setupmethod    def add_url_rule(self, rule, endpoint=None, view_func=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',)        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)        # Methods that should always be added        required_methods = set(getattr(view_func, 'required_methods', ()))        # starting with Flask 0.8 the view_func object can disable and        # force-enable the automatic options handling.        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        # 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

  1. 如果没有提供endpoint,则获取路由函数的名称作为路由规则的endpoint(这里说明,每个路由规则必然带有一个endpoint)
  2. 如果没有提供可选参数“methods”,则默认以GET方法来装饰,所有方法转换为大写
  3. 生成路由规则rule,并且添加到url_map中
  4. 如果路由规则处理函数不为空,则添加到view_functions字典中,key就是endpoint,value则是路由处理函数





原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高一的学生成绩跟不上怎么办 综合素质评价手册丢了怎么办 小学综合素质评价手册丢了怎么办 人体质不出汗差怎么办 儿子一年级语文成绩太差怎么办 小孩读一年级差几个月怎么办 小孩一年级下学期数学差怎么办 小学五年成绩差怎么办 生完孩子记忆力不好怎么办 生了孩子之后记忆力不好怎么办 孩子记忆力差学习不好怎么办 党课结业证丢了怎么办 对三年级不听话的学生应该怎么办 素质报告单丢了怎么办 社保小红本丢了怎么办 小红本丢了怎么办 孩子小红本丢了怎么办 小学素质报告册丢了怎么办 小学生素质报告册丢了怎么办 高中素质报告册丢了怎么办 小升初素质报告单丢了怎么办? 三供一业移交后社区管理职能怎么办 初中政治总考不好怎么办 孩子上初一学习越来越差怎么办 胸经过整容后变得胸闷怎么办? 网瘾高中不学习怎么办 犯罪人逃到美国怎么办 10岁儿童偏胖怎么办 土地面积与实际面积不符怎么办 军转进省直单位双选失败怎么办 房改房楼龄到了70年怎么办 商品房房改房到70年后怎么办 公务员未享受房改政策怎么办 两套房改房违规怎么办 法院保全的物品在我家怎么办 西瓜视频答题结束了钱没提现怎么办 诚信答题密码忘了怎么办 我未成年杀了人怎么办 错过了网课考试怎么办? 2018广东省普法考试0分怎么办 小孩错过了小升初的考试怎么办