使用 Flask-sqlalchemy 进行依赖注入

mat*_*eok 5 dependency-injection sqlalchemy flask flask-sqlalchemy

我正在寻找一种结合使用简单依赖注入的方法flask-sqlalchemy

这是一个示例设置

扩展.py

db = SQLAlchemy()
Run Code Online (Sandbox Code Playgroud)

my_model.py

from extensions import db

class MyModel(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    // ... some more fields
Run Code Online (Sandbox Code Playgroud)

my_model_repository.py

from my_model import MyModel

class MyModelRepository:

    def get_all():
        MyModel.query.all()
Run Code Online (Sandbox Code Playgroud)

现在我想以某种方式注入,db以便MyModelRepository当我对其进行单元测试时,我可以注入一个mock或一个内存数据库,而无需处理任何全局配置或标志。

这是我希望它看起来如何的示例

from my_model import MyModel

class MyModelRepository:

    def __init__(self, db):
        self.db = db

    def get_all():
        db.query(MyModel).all()
Run Code Online (Sandbox Code Playgroud)

然而,这似乎不可能,因为MyModel继承自db.Model并且db已经是 的特定实例SQLAlchemy

使数据库可注入任何依赖于它的组件的适当方法是什么?

V B*_*ota 0

对我来说,它的工作原理是这样的:

  • my_model_repository.py将注入装饰器添加到类的 init中
from my_model import MyModel
from flask_sqlalchemy import SQLAlchemy

class MyModelRepository:
    @inject
    def __init__(self, db: SQLAlchemy):
        self.db = db

    def get_all():
        db.query(MyModel).all()
Run Code Online (Sandbox Code Playgroud)
  • 并在app.py您创建烧瓶应用程序的或另一个源文件中添加:
import flask_injector
from extensions import db

app = Flask(__name__) #something like this should already be in your code

db.init_app(app)

#this function could potentially be moved to it's own file
def configure_dependencies(binder):
    binder.bind(SQLAlchemy, to=db, scope=flask_injector.singleton)

flask_injector.FlaskInjector(app=app, modules=[configure_dependencies])
Run Code Online (Sandbox Code Playgroud)

数据源: