use dependency injection with flask-sqlalchemy

Viewed 861

I am looking for a way to use simple dependency injection in combination with flask-sqlalchemy

Here's an example setup

extensions.py

db = SQLAlchemy()

my_model.py

from extensions import db

class MyModel(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    // ... some more fields

my_model_repository.py

from my_model import MyModel

class MyModelRepository:

    def get_all():
        MyModel.query.all()

Now I would like to somehow inject the db into MyModelRepository so that when I unit test it I can inject a mock or an in-memory database without having to deal with any global config or flags.

Here's an example of how I would want it to look

from my_model import MyModel

class MyModelRepository:

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

    def get_all():
        db.query(MyModel).all()

This however seems to not be possible because MyModel inherits from db.Model and db already is a specific instance of SQLAlchemy.

What is the appropriate way to make the database injectable to any component that depends on it?

1 Answers

For me it worked something like this:

  • In my_model_repository.py add the inject decorator to the init of your class
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()
  • and in your app.py or another source file where you create your flask app add:
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])

Data sources:

Related