Skip to main content

Adds Injector, a Dependency Injection framework, support to Flask.

Project description

Build status

Adds Injector support to Flask, this way there’s no need to use global Flask objects, which makes testing simpler.

Injector is a dependency-injection framework for Python, inspired by Guice.

Flask-Injector is compatible with CPython 3.3+. As of version 0.8.0 it requires Injector version 0.10.0 or greater and Flask 0.11.0 or greater.

GitHub project page: https://github.com/alecthomas/flask_injector

PyPI package page: https://pypi.python.org/pypi/Flask-Injector

Changelog: https://github.com/alecthomas/flask_injector/blob/master/CHANGELOG.rst

Features

Flask-Injector lets you inject dependencies into:

  • views (functions and class-based)

  • before_request handlers

  • after_request handlers

  • teardown_request handlers

  • template context processors

  • error handlers

  • Jinja environment globals (functions in app.jinja_env.globals)

  • Flask-RESTFul Resource constructors

  • Flask-RestPlus Resource constructors

Flask-Injector supports defining types using function annotations (Python 3), see below.

Example application using Flask-Injector

import sqlite3
from flask import Flask, Config
from flask.views import View
from flask_injector import FlaskInjector
from injector import inject

app = Flask(__name__)

# Configure your application by attaching views, handlers, context processors etc.:

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


# In the Injector world, all dependency configuration and initialization is
# performed in modules (http://packages.python.org/injector/#module). 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`:

def configure(binder):
    binder.bind(
        sqlite3.Connection,
        to=sqlite3.Connection(':memory:'),
        scope=request,
    )

# Initialize Flask-Injector. This needs to be run *after* you attached all
# views, handlers, context processors and template globals.

FlaskInjector(app=app, modules=[configure])

# All that remains is to run the application

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',
    )

    # attach your views etc. here

    FlaskInjector(app=app, modules=[configure_ext])

    app.run()

Make sure to bind extension objects as singletons.

Using Python 3+ function annotations

If you want to use function annotations you can either pass use_annotations=True in the FlaskInjector constructor or provide an already configured Injector instance with use_annotations enabled, for example:

from flask import Flask
from flask_injector import FlaskInjector

app = Flask(__name__)

@app.route("/")
def index(s: str):
    return s

def configure(binder):
    binder.bind(str, to='this is a test')

FlaskInjector(app=app, modules=[configure], use_annotations=True)

# Alternatively:
from injector import Injector
injector = Injector(..., use_annotations=True)
FlaskInjector(app=app, injector=injector)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Flask-Injector-0.9.0.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

Flask_Injector-0.9.0-py2.py3-none-any.whl (10.9 kB view details)

Uploaded Python 2Python 3

File details

Details for the file Flask-Injector-0.9.0.tar.gz.

File metadata

File hashes

Hashes for Flask-Injector-0.9.0.tar.gz
Algorithm Hash digest
SHA256 69a84b84f70b33cf1c8c970998fbd028d79357196b9fe636795ef14225ea1167
MD5 80f2dc0e13dc754c29e472485d7ceb36
BLAKE2b-256 b9fd19e90e85d3cf47c3eca76392111b6f464fe01c608e1d044f6b309a49fd8e

See more details on using hashes here.

File details

Details for the file Flask_Injector-0.9.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for Flask_Injector-0.9.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 fc82f49a727b918119ad638854305dab2ef66c5880109ff831d67a661457c0df
MD5 4e1ebaf6a61cce8443f3f8e8aa29d6c6
BLAKE2b-256 2bb1582ef06efda18a4728aa6b20e6d9f20fd9e40022a864b354824b9da254bf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page