modern-di integration for Flask.
Full guide: Flask integration docs
Usage example: examples/
Installation
uv add modern-di-flask # or: pip install modern-di-flask
Usage
Flask has no dependency-injection system of its own, so modern-di-flask pairs an @inject decorator with inert FromDI markers (there is no Depends). setup_di installs a before_request/teardown_appcontext pair that builds a per-request Scope.REQUEST child container and closes it once the request finishes. The child is also built on first use, so request hooks registered before setup_di can use it, and it is closed after every teardown_appcontext handler. Resolution is sync, also for async def views, and the child container is closed with close_sync().
import typing
from flask import Flask
from modern_di import Container, Group, Scope, providers
from modern_di_flask import FromDI, inject, setup_di
class Settings:
def __init__(self) -> None:
self.greeting = "hello"
class Dependencies(Group):
settings = providers.Factory(scope=Scope.APP, creator=Settings)
app = Flask(__name__)
@app.route("/hello/<name>")
@inject
def hello(name: str, settings: typing.Annotated[Settings, FromDI(Dependencies.settings)]) -> str:
return f"{settings.greeting}, {name}"
container = Container(groups=[Dependencies])
setup_di(app, container)
container.validate() # optional fail-fast; must come after setup_di registers its providers
Pass auto_inject=True to setup_di to wire every registered view (app and blueprint routes alike) without a per-view @inject. It walks app.view_functions when setup_di runs, so call setup_di after all routes are registered. flask.Request is resolvable within DI via the pre-built flask_request_provider context provider.
A streamed response (a generator body, with or without stream_with_context) keeps the child container open until the response is closed, which a WSGI server does after sending the body. A stream_with_context generator can resolve from it, and dependencies resolved in the view stay usable while the body streams. A direct_passthrough response, such as one from send_file, is not closed through Flask, so its child container closes at teardown as usual.
async def views work with @inject and with auto_inject=True. Flask runs them through asgiref, so install Flask's async extra (pip install "flask[async]"). The markers are resolved from the request's child container before the view is awaited. Teardown is sync: the child container is closed with close_sync(), so a Scope.REQUEST provider with an async finalizer is not supported and fails when the request ends. The same applies to the root container at shutdown: if an APP-scoped provider has an async finalizer, close the root with asyncio.run(fetch_di_container(app).close_async()) instead of close_sync().
A container is open from construction. To fail fast at boot, call .validate() after setup_di, which registers flask_request_provider. Flask has no shutdown hook, so call fetch_di_container(app).close_sync() at process shutdown.
API
| Symbol | Description |
|---|---|
setup_di(app, container, *, auto_inject=False) |
Registers the container on app.extensions, installs the before_request/teardown_appcontext pair that builds and closes a per-request Scope.REQUEST child, and, if auto_inject=True, wraps every currently registered view with inject; returns the container |
FromDI(dependency) |
Inert marker (used with @inject) that resolves a provider or type from the per-request child container |
inject(view) |
Decorator for a sync or async def view; returns a wrapper of the same kind and resolves its FromDI-annotated parameters without rewriting the function's signature. Raises RuntimeError naming setup_di when a request reaches it without setup_di called |
fetch_di_container(app) |
Returns the root Container stored on app.extensions |
flask_request_provider |
ContextProvider for flask.Request (REQUEST scope), auto-registered by type |
📦 PyPI
📝 License
Part of modern-python
Built on modern-di, a dependency-injection framework with an IoC container and scopes.
Browse the full list of templates and libraries in
modern-python; the org profile has the categorized index.
Metadata
Release files for modern-di-flask 4.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| modern_di_flask-4.2.2.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modern_di_flask-4.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.9 kB
Release files / modern_di_flask-4.2.2.tar.gz
| Download URL | modern_di_flask-4.2.2.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7dfa315f09c9424164490e967301985a8f94c333699deca0490c3f5c3cec9243
|
|
BLAKE2b-256 checksum How to use checksums |
3b23609afc52592e84f4ec79883ac2cef54c00a6ae53e8094e637a43ad02a059
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / modern_di_flask-4.2.2-py3-none-any.whl
| Download URL | modern_di_flask-4.2.2-py3-none-any.whl |
|---|---|
| Size | 6.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4703138d6843071f2d5252f2a3f2d970f6e5a5f9fe84dbb5f629b98b5dee4850
|
|
BLAKE2b-256 checksum How to use checksums |
e520fd8825bc1ad39839880606c0f6691a6e62c5bb0df1b328b5d4061d686e59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|