Starlette DI
Starlette DI is a dependency injection library for Starlette applications. It simplifies dependency management by allowing services to be injected using Scoped, Transient, and Singleton lifetimes (similar to .NET Core). Also, enables automatic injection of route parameters, and request bodies using Pydantic models, making API development more efficient, and structured.
Table of Contents
Features
- Scoped, Transient, and Singleton: Dependency injection with three service lifetimes, similar to .NET Core.
- Service Injection: Supports injecting services into functions, methods, and endpoint classes in Starlette.
- Route Parameter Injection: Automatically extracts URL parameters in controllers.
- Request Body Injection: Maps JSON request body data directly to Pydantic models.
- Dependency Injection Middleware: Provides a middleware layer to manage dependency injection throughout the request lifecycle.
- Pydantic Compatibility: Leverages Pydantic for data validation, and conversion.
- Decorators for Endpoints: Simplifies injection with
@inject,@inject_method, and@inject_class.
Requirements
Python>=3.10Starlette>=0.38.0Pydantic>=1.10.21
Installation
You can simply install starlette-di from PyPI:
pip install starlette-di
Tutorial
1. Create a service
Define a service that can be injected:
from abc import ABC, abstractmethod
class IGreeter(ABC):
@abstractmethod
def greet(self) -> str: ...
class Greeter(IGreeter):
def greet(self) -> str:
return 'Hello!'
Alternatively, use a factory function:
def greeter_factory() -> IGreeter:
return Greeter()
2. Configure dependency injection
Use a ServiceCollection to register services with different lifetimes:
- Singleton: one instance for the application lifetime.
- Scoped: one instance per request.
- Transient: new instance created each time it's requested.
Example:
from starlette_di import ServiceCollection
services = ServiceCollection()
services.add_transient(IGreeter, Greeter)
# also, services.add_scoped(IGreeter, Greeter)
# or services.add_singleton(IGreeter, Greeter)
provider = services.build_provider()
Using a factory function:
def greeter_factory() -> IGreeter:
return Greeter()
services.add_transient(IGreeter, greeter_factory)
3. Injecting services
Use the @inject, @inject_method, and @inject_class decorators to inject
the service into an endpoint function, method or class respectively.
Inject into an endpoint function
Inject the service into an endpoint function using the @inject decorator:
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette_di import inject
@inject
async def greet(request: Request, greeter: IGreeter):
return JSONResponse({'message': greeter.greet()})
Inject into an endpoint method
Inject the service into an endpoint method using the @inject_method decorator:
from starlette.requests import Request
from starlette.endpoints import HTTPEndpoint
from starlette.responses import JSONResponse
from starlette_di import inject_method
class GreetEndpoint(HTTPEndpoint):
@inject_method
async def get(self, request: Request, greeter: IGreeter):
return JSONResponse({'message': greeter.greet()})
Inject into an endpoint class
Inject the service into an endpoint class using the @inject_class decorator:
from starlette.responses import JSONResponse
from starlette.endpoints import HTTPEndpoint
from starlette_di import inject_class
@inject_class
class GreetEndpoint(HTTPEndpoint):
def __init__(self, request: Request, greeter: IGreeter):
super().__init__(request)
self.greeter = greeter
async def get(self, request: Request):
return JSONResponse({'message': self.greeter.greet()})
4. Inject path params
You can inject request path parameters:
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette_di import inject
@inject
async def greet_person(self, request: Request, name: str):
return JSONResponse({'message': f'Hello {name}!'})
routes = [
Route('/greet/{name:str}', greet_person),
]
5. Inject request body
Also, you can inject the request body using Pydantic models. If there's only one Pydantic model parameter, the whole JSON body is injected. Otherwise, each parameter is extracted from the JSON body using its name.
Only one parameter:
from pydantic import BaseModel
from starlette.requests import Request
from starlette.responses import JSONResponse
class User(BaseModel):
name: str
age: int
@inject
async def create_user(request: Request, user: User):
return JSONResponse({'name': user.name, 'age': user.age})
# Example request
# {'name': 'Jane Doe', 'age': 25}
Two or more parameters
from pydantic import BaseModel
from starlette.requests import Request
from starlette.responses import JSONResponse
class User(BaseModel):
name: str
age: int
class Product(BaseModel):
name: str
price: float
@inject
async def update_product(request: Request, user: User, product: Product):
return JSONResponse({'user_name': user.name, 'product_name': product.name})
# Example request
# {
# 'user': {'name': 'Jane Doe', 'age': 25},
# 'product': {'name': 'Computer', 'price': 225.0},
# }
6. Use the DependencyInjectionMiddleware
Use the DependencyInjectionMiddleware to handle dependency injection.
This middleware sets up the request scope for dependency injection by creating a scoped service provider, and adding it to the request scope.
Pass the service provider built in here to
the service_provider argument of the middleware:
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.routing import Route
from starlette_di import DependencyInjectionMiddleware
app = Starlette(
routes=[Route('/greet', GreetEndpoint)],
middleware=[
Middleware(DependencyInjectionMiddleware, service_provider=provider),
]
)
Full example
Find the full tutorial example here.
Contributing
See the contribution guidelines.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Support
If you find this project useful, give it a ⭐ on GitHub!
Metadata
Release files for starlette-di 0.1.1
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 | Actions |
|---|---|---|---|---|
| starlette_di-0.1.1.tar.gz | 16.0 kB | With provenance | Details for starlette_di-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| starlette_di-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for starlette_di-0.1.1-py3-none-any.whl |
Total release size: 30.1 kB
Release files / starlette_di-0.1.1.tar.gz
| Download URL | starlette_di-0.1.1.tar.gz |
|---|---|
| Size | 16.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2f73be0de3658acd8e87e191769a9183f331d92f482a4766c4e8bd9233df0fcf
|
|
BLAKE2b-256 checksum How to use checksums |
0f2ecaf7638e90f4797039225b27f86f75a9a4d5231566fcaf89787601cbde12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2025.
Transparency logRelease files / starlette_di-0.1.1-py3-none-any.whl
| Download URL | starlette_di-0.1.1-py3-none-any.whl |
|---|---|
| Size | 14.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ebc64997bfabf9c1c84b8bcce5bcdcb6d3a32189f4f6a3f65f63e4b38ad3f692
|
|
BLAKE2b-256 checksum How to use checksums |
569c5b1ccc2522f80a668c3e769771b6fbb722b45d86f4a493197a63676f285a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2025.
Transparency logSecurity for starlette-di 0.1.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for starlette_di-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2025.
Transparency logA 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.