python學習筆記-flask學習(二)BulePrint


  app.route定義的裝飾器只有在app實例創建后才能運行。如果需要將app之前是由route來添加路由規則和功能或者將路由和app接耦合,在這種場景下Blueprint提供很好的解決方法。在藍本定義的路由規則處於休眠狀態,直到這個藍圖注冊到app中。

  藍圖定義: 

auth = Blueprint('auth',__name__)

@auth.route('/logout')
def logout():
    pass

這里完成的工作只是創建一個藍圖並將路由加入藍圖中

from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint,url_prefix='/auth')

這里將藍圖中注冊的路由添加到app實例中。下面來分析下藍圖的工作原理:

auth.route('/logout')裝飾器的源碼如下

    def route(self, rule, **options):
        """Like :meth:`Flask.route` but for a blueprint.  The endpoint for the
        :func:`url_for` function is prefixed with the name of the blueprint.
        """
        def decorator(f):
            endpoint = options.pop("endpoint", f.__name__)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

route調用add_url_rule函數,add_url_rule函數其實是調用record函數將下面的一個匿名函數對象傳入到deferred_functions的列表中,這個在register將調用注冊這些匿名函數。add_url_rule函數代碼如下:

    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        """Like :meth:`Flask.add_url_rule` but for a blueprint.  The endpoint for
        the :func:`url_for` function is prefixed with the name of the blueprint.
        """
        if endpoint:
            assert '.' not in endpoint, "Blueprint endpoints should not contain dots"
        self.record(lambda s:
            s.add_url_rule(rule, endpoint, view_func, **options))

到此藍圖中注冊路由就完成了。接下來是注冊實現的原理

首先調用Flask對象的register_blueprint函數,這個函數調用blueprint的register處理處理藍圖的注冊。

    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)
blueprint的register函數調完成了一下功能首先make_setup_state創建了BlueprintSetupState實例。然后將這個實例作為deferred_functions中存儲的匿名函數的入參。調用的BlueprintSetupState的add_rule_url函數,而在
BlueprintSetupState的add_rule_url函數其實最終調用的flask的add_rule_url
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)
    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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM