Subclass AioinjectMiddleware
Since Django doesn't allow you to parametrize middleware (e.g. like starlette does)
we need to subclass AioinjectMiddleware
:
app/di.py
alternatively you can declare a property if needed:
import functools
import random
from aioinject import Scoped, SyncContainer
from aioinject.ext.django import SyncAioinjectMiddleware
@functools.cache
def create_container() -> SyncContainer:
container = SyncContainer()
container.register(
Scoped(lambda: random.randint(1, 1000), interface=int), # noqa: S311
)
return container
class DIMiddleware(SyncAioinjectMiddleware):
container = create_container()
class DIMiddleware(SyncAioinjectMiddleware):
@property
def container(self) -> SyncContainer:
return create_container()
Add middleware to your settings.MIDDLEWARE
app/settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"app.di.DIMiddleware",
]
Mark your view with @inject
views.py
from django.http import HttpRequest, HttpResponse
from aioinject import Injected
from aioinject.ext.django import inject
@inject
def root_view(
_: HttpRequest,
dependency: Injected[int],
) -> HttpResponse:
return HttpResponse(content=f"{dependency}")
Warning
Since django and rest_framework pass request as a positional argument your request parameter should always be declared first.
Integration with Rest Framework
@inject
decorator should work with any function/method that accepts
django.http.HttpRequest
or rest_framework.request.Request
:
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet
from aioinject import Injected
from aioinject.ext.django import inject
class ViewExample(APIView):
@inject
def get(self, _: Request, number: Injected[int]) -> Response:
return Response({"value": number})
class ViewSetExample(ViewSet):
@inject
def retrieve(
self,
_: Request,
pk: int,
number: Injected[int],
) -> Response:
return Response({"id": pk, "value": number})