Adds Injector, a Dependency Injection framework, support to Flask.
Project description
Adds Injector support to Flask.
Injector is a dependency-injection framework for Python, inspired by Guice.
This way there’s no need to use global Flask objects, which makes testing simpler.
Flask-Injector is compatible with CPython 2.5-2.6, 3.3+ and PyPy 1.9+.
Example application using flask_injector
Create your Flask application:
import sqlite3
from flask import Flask, Config
from flask.views import View
from flask_injector import init_app, post_init_app
from injector import Injector, inject
app = Flask(__name__)
Update the Flask app configuration as normal, additionally passing in any configuration for modules:
app.config.update(
DB_CONNECTION_STRING=':memory:',
)
In the Injector world, all dependency configuration and initialization is performed in modules. The same is true with Flask-Injector. You can see some examples of configuring Flask extensions through modules below.
Accordingly, the next step is to create modules for any objects we want made available to the application. Note that in this example we also use the injector to gain access to the flask.Config:
# Configure our SQLite connection object
@inject(config=Config)
def configure(binder, config):
binder.bind(
sqlite3.Connection,
to=sqlite3.Connection(config['DB_CONNECTION_STRING']),
scope=request,
)
Now perform Injector Flask application integration initialization. This needs to be run before any views, handlers, etc. are configured for the application:
injector = init_app(app=app, modules=[configure])
You can also provide already existing Injector instance:
injector = your_initialization_code()
# ...
init_app(app=app, injector=injector)
Configure your application by attaching views, handlers, context processors etc.:
# Putting all views configuration in a function is an example of how can
# you stop depending on global app object
def configure_views(app):
@app.route("/bar")
def bar():
return render("bar.html")
# Route with injection
@app.route("/foo")
@inject(db=sqlite3.Connection)
def foo(db):
users = db.execute('SELECT * FROM users').all()
return render("foo.html")
# Class-based view with injected constructor
class Waz(View):
@inject(db=sqlite3.Connection)
def __init__(self, db):
self.db = db
def dispatch_request(self, key):
users = self.db.execute('SELECT * FROM users WHERE name=?', (key,)).all()
return 'waz'
app.add_url_rule('/waz/<key>', view_func=Waz.as_view('waz'))
configure_views(app)
Run the post-initialization step. This needs to be run only after you attached all views, handlers etc.:
post_init_app(app=app, injector=injector)
Run the Flask application as normal:
app.run()
See example.py for a more complete example, including Flask-SQLAlchemy and Flask-Cache integration.
Supporting Flask Extensions
Typically, Flask extensions are initialized at the global scope using a pattern similar to the following.
app = Flask(__name__)
ext = ExtClass(app)
@app.route(...)
def view():
# Use ext object here...
As we don’t have these globals with Flask-Injector we have to configure the extension the Injector way - through modules. Modules can either be subclasses of injector.Module or a callable taking an injector.Binder instance.
@inject(app=Flask)
def configure_ext(binder, app):
binder.bind(ExtClass, to=ExtClass(app), scope=singleton)
def main():
app = Flask(__name__)
app.config.update(
EXT_CONFIG_VAR='some_value',
)
injector = init_app(app=app, modules=[configure_ext])
# attach your views etc. here
post_init_app(app=app, injector=injector)
app.run()
Make sure to bind extension objects as singletons.
Working Example 1: Flask-SQLAlchemy integration
This is a full working example of integrating Flask-SQLAlchemy.
We use standard SQLAlchemy models rather than the Flask-SQLAlchemy magic.
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String
Base = declarative_base()
class KeyValue(Base):
__tablename__ = 'data'
key = Column(String, primary_key=True)
value = Column(String)
def __init__(self, key, value):
self.key = key
self.value = value
And to register the Flask-SQLAlchemy extension.
from flast.ext.sqlalchemy import SQLAlchemy
@inject(app=Flask)
class FlaskSQLAlchemyModule(Module):
def configure(self, binder):
db = self.configure_db(self.app)
binder.bind(SQLAlchemy, to=db, scope=singleton)
def configure_db(self, app):
db = SQLAlchemy(app)
Base.metadata.create_all(db.engine)
db.session.add_all([
KeyValue('hello', 'world'),
KeyValue('goodbye', 'cruel world'),
])
db.session.commit()
return db
Working Example 2: Flask-Cache integration
@inject(app=Flask)
class CacheModule(Module):
"""Configure the application."""
def configure(self, binder):
binder.bind(Cache, to=Cache(self.app), scope=singleton)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file Flask-Injector-0.3.2.tar.gz
.
File metadata
- Download URL: Flask-Injector-0.3.2.tar.gz
- Upload date:
- Size: 5.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d808a98a4e9706bfa1d0003363de0efbbc9a88f2406745acf3fc18629afca9a0 |
|
MD5 | b75498494f6e2667f122a0b83f2fd51d |
|
BLAKE2b-256 | 0ba696764cd600d25fb5a5af772762fa1b930675126fdc7a774c921c28da2a9a |
Provenance
File details
Details for the file Flask_Injector-0.3.2-py2.py3-none-any.whl
.
File metadata
- Download URL: Flask_Injector-0.3.2-py2.py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ef86b665e18bb511bb8067b37c0c6d5e6810e87d5f33d6ed5f101a7155ed2009 |
|
MD5 | 062d84d7895b0507ccbae10117503b8f |
|
BLAKE2b-256 | 5344e44e61eabea25a049d1e940951687412a0ee1d62736f0d41629fc2e04563 |