如何理解flask中的blueprint的参数

发布于 2022-09-06 23:08:58 字数 565 浏览 17 评论 0

文件结构:
|--hello.py
|--admin
    |--__init__.py
    |--admin.py
    

hello.py

from flask import Flask
from admin.admin import admin

app = Flask(__name__)
app.register_blueprint(admin, url_prefix='/admin')

admin.py

from flask import Blueprint

admin = Blueprint('666', __name__)

@admin.route('/')
def index():
    return '<h1>X</h1>'
    

__init__.py
空文件

我这里的疑问是admin = Blueprint('666', __name__)中的参数'666'改成什么程序都可以正常运行,那么这个参数究竟指的是什么,在什么位置?
谢谢!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离线来电— 2022-09-13 23:08:58

我一直以为 Blueprint 中的 name 参数和 url_for 中所用到的 endpoint (端点)有关,下面是我为什么这样理解的。

首先,我们看一下 flask 的源码: https://github.com/pallets/fl...
其中,有下面的代码:

class Blueprint(_PackageBoundObject):
    ...
    ...
    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 类继承了 _PackageBoundObject,其中,name 参数,可是该类自己定义的,那么,我们继续在源码中找 name 参数的作用。

在该类中寻找 self.name, 我们可以看到另外 8 处内容, 分别在该类的 before_request、after_request、teardown_request、context_processor、url_value_preprocessor、url_defaults、errorhandler、register_error_handle 这 8 个类函数中,基本上函数中用到的地方都是:

 self.record_once(lambda s: s.app.before_request_funcs
            .setdefault(self.name, []).append(f))

那么,我们再看看这个 record_once 函数的作用,该函数也是在该类中定义的

    def record_once(self, func):
        """Works like :meth:`record` but wraps the function in another
        function that will ensure the function is only called once.  If the
        blueprint is registered a second time on the application, the
        function passed is not called.
        """
        def wrapper(state):
            if state.first_registration:
                func(state)
        return self.record(update_wrapper(wrapper, func))

通过注释,很明显地看到这个函数的作用是为了将 name 参数作为唯一标识来在程序中区分蓝图所用的。

那么,回到题主的问题。
一、之所以可以随便定义名称,感觉没有什么影响,那是错觉。

  • 第一个原因,你值定义了一个蓝图,如果你再定义一个,你把 name 的参数设置成一样的,你试试程序会不会报错。
  • 第二个原因,你没有用到 url_for 函数,这个函数中会用到你的 name 参数,或者你是直接在这样简化的调用的 url_for('.index') 函数的, 那个 '.' 代表了当前的蓝图。
  • 还是回到 url_for 函数,如果你在 html 的 jinja2 中调用,你得这样写 url_for('name.index'),其中的 name 就是你定义的蓝图的 name 参数。

二、你可以试试如果不定义 name 参数,程序会报错,因为这个参数是必须的。

  • 在 view 视图中,我们使用 装饰器 的写法,一般是把函数名称当做 endpoint 的,如果你在两个不同的蓝图中,使用同一个名称来定义视图函数,那么 endpoint 按照默认方案就无法是唯一标识了,必须得加上蓝图的名称,所以蓝图的名称也得是唯一的。
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文