flask创建蓝本如何理解“导入views,errors模块就能把路由和错误处理程序与蓝本关联起来”?

如题,创建蓝本的代码如下:

from flask import Blueprint
main = Blueprint('main', __name__)

from . import views, errors

《flask web开发》书里面解释:程序的路由保存在包里的app/main/views.py模块中,而错误处理程序保存在app/main/errors.py模块中。导入这两个模块就能把路由和错误处理程序与蓝本关联起来。
最后一句话不理解,为何只是导入两个模块就能关联,并没有进行其他的操作。
个人理解,在__init__.py程序末尾导入两个模块,而两个模块也导入了__init__.py,而在views.py中,有

from . import main

@main.route('/',methods=['GET','POST'])

在errors.py中

from . import main

@main.app_errorhandler(404)

因此蓝本与errors和views关联起来了。那这样是否可以在main.py中省略最后一句?不知道这样理解是否正确,还是有其他的深层关系?希望有人讲解一下,谢谢!

阅读 4.3k
2 个回答

首先,不明白main.py在哪里??
其次,这个问题,和蓝本无关,即使最简单的、抛弃了蓝图的flask程序的架构模式,也需要在app/__init__.py中写入如下代码:from app import views,errors

装饰器在文件导入的时候就会运行,然后从flask源码分析

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

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))
        
def record(self, func):
    """Registers a function that is called when the blueprint is
    registered on the application.  This function is called with the
    state as argument as returned by the :meth:`make_setup_state`
    method.
    """
    if self._got_registered_once and self.warn_on_modifications:
        from warnings import warn
        warn(Warning('The blueprint was already registered once '
                     'but is getting modified now.  These changes '
                     'will not show up.'))
    self.deferred_functions.append(func)

deferred_functions这个列表会在app注册蓝图的时候,执行里面的方法,如下

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)

到这里才真的将路由注册到装饰器里,所以from . import view应该是有必要的,如果你试出来没必要可以一起学习下

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题