Skip to main content

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

Project description

https://codecov.io/gh/alecthomas/flask_injector/branch/master/graph/badge.svg https://github.com/alecthomas/flask_injector/workflows/CI/badge.svg

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. You can find Injector on PyPI and Injector documentation on Read the Docs.

Flask-Injector is compatible with CPython 3.7+. As of version 0.15.0 it requires Injector version 0.20.0 or greater and Flask 2.2.0 or greater.

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

PyPI package page: https://pypi.org/project/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-RESTX Resource constructors

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

Documentation

As Flask-Injector uses Injector under the hood you should find the Injector documentation, including the Injector API reference, helpful. The Injector README provides a tutorial-level introduction to using Injector.

The Flask-Injector public API consists of the following:

  • FlaskInjector class with the constructor taking the following parameters:

    • app, an instance of`flask.Flask` [mandatory] – the Flask application to be used

    • modules, an iterable of Injector modules [optional] – the Injector modules to be used.

    • injector, an instance of injector.Injector [optional] – an instance of Injector to be used if, for some reason, it’s not desirable for FlaskInjector to create a new one. You’re likely to not need to use this.

    • request_scope_class, an injector.Scope subclass [optional] – the scope to be used instead of RequestScope. You’re likely to need to use this except for testing.

  • RequestScope class – an injector.Scope subclass to be used for storing and reusing request-scoped dependencies

  • request object – to be used as a class decorator or in explicit bind() calls in Injector modules.

Creating an instance of FlaskInjector performs side-effectful configuration of the Flask application passed to it. The following bindings are applied (if you want to modify them you need to do it in one of the modules passed to the FlaskInjector constructor):

  • flask.Flask is bound to the Flask application in the (scope: singleton)

  • flask.Config is bound to the configuration of the Flask application

  • flask.Request is bound to the current Flask request object, equivalent to the thread-local flask.request object (scope: request)

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")
def foo(db: sqlite3.Connection):
    users = db.execute('SELECT * FROM users').all()
    return render("foo.html")


# Class-based view with injected constructor
class Waz(View):
    @inject
    def __init__(self, db: sqlite3.Connection):
        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 (https://injector.readthedocs.io/en/latest/terminology.html#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.

from injector import Module

class MyModule(Module):
    @provider
    @singleton
    def provide_ext(self, app: Flask) -> ExtClass:
        return ExtClass(app)

def main():
    app = Flask(__name__)
    app.config.update(
        EXT_CONFIG_VAR='some_value',
    )

    # attach your views etc. here

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

    app.run()

Make sure to bind extension objects as singletons.

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.15.0.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

Flask_Injector-0.15.0-py2.py3-none-any.whl (14.1 kB view details)

Uploaded Python 2 Python 3

File details

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

File metadata

  • Download URL: Flask-Injector-0.15.0.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.12

File hashes

Hashes for Flask-Injector-0.15.0.tar.gz
Algorithm Hash digest
SHA256 567c69da7657b96565db990bb7c87cc0acf04e383714341954902f1ef85c5875
MD5 705ef1aa9f960a7aa8628519b1e1d507
BLAKE2b-256 70f1c9a83644c62ef7b0dec8c10d5dc18d83bd145eb442ab778279ab847e0683

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for Flask_Injector-0.15.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 9908904ab8d8830e5160b274fd5dd73453741c9c618d3fc6deb2b08d894f4ece
MD5 6c49545eef2f7450efd404152b6543ac
BLAKE2b-256 44a0e7964d1d1b8fb64c62988de6a20ee06573354e0a0d9653b6e659323920e9

See more details on using hashes here.

Supported by

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