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 |
Links
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.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| modern_di_flask-4.2.3.tar.gz | 5.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modern_di_flask-4.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.9 kB
Release files / modern_di_flask-4.2.3.tar.gz
| Download URL | modern_di_flask-4.2.3.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6ece9c9fa1480634de4dc35c78d4b5fc7ac265a02f04f9d5d279bc20c9d6426f
|
|
BLAKE2b-256 checksum How to use checksums |
aace8f94f42b830e03f3fe518cbe5321838d53fcd9c6abebbda62ef316baf37a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","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.3-py3-none-any.whl
| Download URL | modern_di_flask-4.2.3-py3-none-any.whl |
|---|---|
| Size | 6.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdb808b8a3fb97a6a979c36f8284b155c8b22512394f9a1fe12dbd8b3f24405b
|
|
BLAKE2b-256 checksum How to use checksums |
dd245ee029db3605662179a039867e887fbe40a45e5a7e924688bb67b5652527
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","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}
|
Security for modern-di-flask 4.2.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.