繁体   English   中英

在运行时更改蓝图或重新加载Flask应用

[英]Change blueprints or Reload flask app during runtime

我正在编写支持插件体系结构的Flask应用程序。 每个插件都位于一个单独的文件夹中,并且是一个模块,该模块至少具有一个子类,该子类是Plugin类的子类。 出于安全原因,我不想在最初运行flask应用程序时加载所有插件。 相反,用户可以从flask应用程序内启用插件。 他执行此操作后,我们会将备忘录存储在数据库中,该备忘录将要加载的应用列入白名单。 但是,我们仍然必须记住禁用了哪些插件并证明了这些插件的视图。 为此,我为未启用且未加载任何自定义代码的插件创建了一个虚拟类。

每个插件都有其自己的蓝图。 我们在加载插件时进行注册。 蓝图还定义了启用插件的路径。 整个过程看起来像这样:

for plugin_name in os.listdir(plugin_dir):
    plugin_path = os.path.join(plugin_paths, plugin_name)
    module_name = "plugins.{}.__init__".format(plugin_name)
    plugin_enabled = ask_db_whether_plugin_is_enabled(plugin_name)

    if os.path.isdir(plugin_path) and plugin_enabled:
        module = __import__(module_name)
        for plugin in load_plugins_from_module(module):
            app.register_blueprint(plugin.blueprint, url_prefix='/plugins')
    else:
        PluginCls = type(identifier, (Plugin, ), {})
        disabled_plugin = PluginCls()
        app.register_blueprint(disabled_plugin.blueprint, url_prefix='/plugins')

load_plugins_from_module看起来像这样:

def load_plugins_from_module(module):
    def is_plugin(c):
        return inspect.isclass(c) and \
               issubclass(c, Plugin) and \
               c != Plugin

    for name, objects in inspect.getmembers(module, lambda c: inspect.ismodule(c)):
        for name, PluginCls in inspect.getmembers(objects, is_plugin):
            plugin = PluginCls()
            yield plugin

现在的问题如下:当我将插件更改为启用时,我基本上想重新运行

module = __import__(module_name)
for plugin in load_plugins_from_module(module):
    app.register_blueprint(plugin.blueprint, url_prefix='/plugins')

该插件的模块,以便它变为活动状态并注册在子类插件中定义的所有路由。 这将引发AssertionError因为我无法在运行时更改蓝图。 有什么好的解决方法? 我可以从应用程序内重新加载应用程序吗? 我可以在运行时修改现有的蓝图吗?

谢谢你的帮助!

我不确定是否需要将其复杂化。

您只需为要启用的插件设置配置选项。 您可以在“ Start_app()”方法中基于该配置注册蓝图。

您还可以动态地将配置选项设置为从某些文件夹/文件继承,例如使其更具动态性。

插件通常是由开发人员开发的,因此配置选项并不繁琐,除非您尝试构建每个随机用户都可以修改您的网站的东西,否则可能会带来巨大的安全问题。

出于安全原因,我不想在最初运行flask应用程序时加载所有插件。

我对此不确定。 不允许用户手动启动插件会带来更大的安全风险(因此,如果用户秘密地能够上传代码,然后现在他可以启用它们)。

您可以像WordPress一样通过启用插件的方式来创建CMS,只需在用户单击“激活插件”之前不路由插件的url。

我不确定如何在运行时修改应用程序对象,但是有另一种方法可以尝试满足您的需求。

  • 创建一个名为“插件”的表,并在其中包含2列:

     Field 1: Blueprint name Field 2: isActive 
  • 为用户提供一个界面,使他们可以“激活”所需的插件。 您可以根据需要控制对其的访问。 因此,您可以编写如下视图:

     @login_required def activate_plugin(name): #whatever code is needed to activate the flag in Plugins table. 
  • 蓝图可以具有before_request()方法,可用于检查是否启用了插件/蓝图。 如果未启用,则返回404或任何代码。

     @blueprintname.before_request def check_if_active(blueprintname): is_active = some_function_that_checks_plugin_active_flag() if is_active: #Normal processing else: abort(404) 
  • 这样,对蓝图视图的每个请求都将首先检查它是否处于活动状态,然后再返回响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM