gpt4 book ai didi

flask - 如何管理应用程序工厂模式中的额外模块?

转载 作者:行者123 更新时间:2023-12-03 17:14:14 25 4
gpt4 key购买 nike

我正在将 Flask 与应用程序工厂模式一起使用。我确实知道应用程序工厂模式仅在工厂函数中管理配置对象。 (如下面的代码)

def create_app(config):
app.config.from_object(config)
sentry.init(app)
...

return app

但是我如何管理需要该配置但无法在应用程序创建时初始化的额外模块?

所以我想做一些类似的事情

def create_app(config):
some_module_obj = Module(host=config.host, port=config.port)

app.config.from_object(config)
sentry.init(app)

return some_module_obj, app

而不是

# I don't want to use `config` outside of the `create_app` function!
some_module_obj = Module(host=config.host, port=config.port)

def create_app(config):
app.config.from_object(config)
sentry.init(app)

return app

最佳答案

不确定这就是您所需要的,但您在评论中要求提供一个带有 inject + Flask 的小示例。据我了解,主要问题与 Flask + 配置 + 初始化有关。这只是其工作原理的一个示例。

app.py:

from flask import Flask

from api import bp
from configurator import configure


def create_app():
app = Flask(__name__)
# configure Flask app config as you wish... (app.config.from_object(config))
# just some settings for demonstration
app.config.update(dict(
MODULE1_TIMER=1,
MODULE2_LIMIT=2,
))
# configure inject using app context and Flask config
with app.app_context():
configure()
# demo blueprint
app.register_blueprint(bp)

return app


if __name__ == '__main__':
create_app().run(debug=True)

假设我们有一些模块:

# mod1.py
class Module1:
def __init__(self, timer: int) -> None:
self._timer = timer

# mod2.py
class Module2:
def __init__(self, limit: int) -> None:
self._limit = limit

def get_limit(self):
return self._limit

# mod3.py - works with mod1 and mod2
class Module3:
def __init__(self, module1, module2) -> None:
self._module1 = module1
self._module2 = module2

def get_limit(self):
return self._module2.get_limit()

配置器.py:

import inject
from flask import current_app

from mod1 import Module1
from mod2 import Module2
from mod3 import Module3


@inject.params(
module1=Module1,
module2=Module2,
)
def _init_module3(module1, module2):
# module1 and module2 are injected instances
return Module3(module1, module2)


def _injector_config(binder):
# initialization of Module1 and Module2 using Flask config
binder.bind(Module1, Module1(current_app.config['MODULE1_TIMER']))
binder.bind(Module2, Module2(current_app.config['MODULE2_LIMIT']))
# initialization of Module3 using injected Module1 + Module2
# you can use bind_to_constructor + any function
binder.bind_to_constructor(Module3, _init_module3)


def configure():
def config(binder):
binder.install(_injector_config)
# one more binder.install... etc...

inject.clear_and_configure(config)

api.py:

import inject
from flask import Blueprint, jsonify

from mod1 import Module1
from mod2 import Module2
from mod3 import Module3

bp = Blueprint('api', __name__)


@bp.route('/test')
def test():
# get instances which was created using inject
return jsonify(dict(
module1=str(type(inject.instance(Module1))),
module2=str(type(inject.instance(Module2))),
module3=str(type(inject.instance(Module3))),
))


# you can inject something as arg
@bp.route('/test2')
@inject.params(module3=Module3)
def test2(module3: Module3):
return jsonify(dict(module3=str(type(module3))))


@bp.route('/test3')
def test3():
# you can inject something into anything
class Example:
module3 = inject.attr(Module3)

@inject.params(module2=Module2)
def __init__(self, module2: Module2) -> None:
self.module2 = module2

return jsonify({
'MODULE2_LIMIT': Example.module3.get_limit(),
'example': dir(Example()),
})

运行服务器,打开/testtest2/test3

关于好处的几句话:

  • 一次初始化和配置
  • 降低对 current_app、flask 配置/上下文等的依赖。
  • 减少递归导入的问题
  • 易于编写测试

希望这有帮助。

关于flask - 如何管理应用程序工厂模式中的额外模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52587523/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com