在运行期间更改蓝图或Reload烧瓶应用程序 [英] Change blueprints or Reload flask app during runtime

查看:87
本文介绍了在运行期间更改蓝图或Reload烧瓶应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个支持插件体系结构的Flask应用程序。每个插件都位于一个单独的文件夹中,并且是一个至少包含一个类的模块,该子类是 Plugin 类的子类。出于安全原因,我不想在烧瓶应用程序最初运行时加载所有插件。相反,用户可以在烧瓶应用程序中启用插件。一旦他这样做,我们在数据库中存储一个备忘录,白名单应用程序加载。但是,我们仍然需要记住哪些插件被禁用,并且证明了这些插件的视图。我通过为插件创建一个虚拟类来实现这一点,这个插件没有被启用,不会加载任何自定义代码。

每个插件都带有自己的蓝图。我们注册,当我们加载插件。 Blueprint也定义了启用插件的路线。
整件事看起来像这样:os.listdir(plugin_dir)中的plugin_name的


$ b

 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)

如果os.path.isdir(plugin_path)和plugin_enabled:
module = __import __(module_name)
for load_plugins_from_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(modu (c)和b
c!=插件

用于inspect.getmembers(module,lambda c:inspect.ismodule(c))中的名称,对象:
用于名称,inspect.getmembers(objects,is_plugin)中的PluginCls:
插件= PluginCls()
yield插件

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

  module = __import __(module_name)
for load_plugins_from_module模块):
app.register_blueprint(plugin.blueprint,url_prefix ='/ plugins')

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



感谢您的帮助!

解决方案

我不知道如何在运行时修改应用程序对象,但有一种替代方法可以尝试您所需要的。


     字段1:蓝图名称

    字段2:isActive


  • 可以激活所需的插件。您可以根据需要控制对其的访问。所以你可以写一个视图,例如:

    $ $ $ $ $ $ $ $ $ b $ activate
    #无论需要什么代码来激活插件表中的标志。


  • 蓝图可以有一个before_request()方法,可以用来检查插件/蓝图已启用。如果不启用,则返回404或任何代码。

    $ p $ @ blueprintname.before_request
    def check_if_active(blueprintname):

    is_active = some_function_that_checks_plugin_active_flag()
    如果is_active:
    #正常处理
    else:
    abort(404)


  • 这样,蓝图视图的每个请求都会在返回响应之前首先检查它是否处于活动状态。



I'm writing a Flask app that supports a plugin architecture. Each plugin lives in a separate folder and is a module that has at least one class which subclasses a Plugin class. For security reasons, I don't want to load all the plugins when the flask app is initially run. Instead, the user can enable plugins from within the flask app. Once he does that, we store a memo in the database that whitelists the app for loading. However, we still have to remember which plugins are disabled and proved views for these plugins. I do that by creating a dummy class for plugins that are not enabled that don't load any custom code.

Each plugin comes with its own Blueprint. We register that when we load the plugins. The Blueprint defines a route for enabling the plugin as well. The whole thing looks like this:

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 looks like this:

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

Now the question is the following: when I change a plugin to enabled, I basically want to re-run

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

for that plugin's module so that it becomes active and registers all routes that have been defined in the subclassed plugin as well. That will raise an AssertionError because I can't change blueprints at runtime. What would be a good work-around for that? Can I reload the app from within the app? Can I modify the existing blueprint at runtime?

Thanks for your help!

解决方案

I am not sure how to modify the app object at runtime but there is an alternative way that you possibly try for what you need.

  • Create a table called "Plugins" and have 2 columns in it:

    Field 1: Blueprint name
    
    Field 2: isActive
    

  • Provide an interface to users where they can "activate" the desired plugin. You can control access to it as needed. So you can write a view such as:

    @login_required
    def activate_plugin(name):
    
    #whatever code is needed to activate the flag in Plugins table.
    

  • Blueprints can have a before_request() method that you can use to check if a plugin/blueprint is enabled. if not enable, return 404 or whatever code.

    @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)
    

  • This way, every request to a blueprint view will first check if it is active before returning the response.

这篇关于在运行期间更改蓝图或Reload烧瓶应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆