Skip to content

Inject in Views

Use @inject for request-scoped Django callables.

This includes:

  • Core Django function-based and class-based views
  • DRF endpoints
  • Django Ninja endpoints
  • Forms or model methods that execute during a request

For non-request entry points (commands, signals, checks, scripts), use @inject_app: App-Level Injection.

Core Django Views

views.py
from django.http import HttpRequest, HttpResponse
from wireup import Injected
from wireup.integration.django import inject

from myapp.services import GreeterService


@inject
def greet(
    request: HttpRequest, greeter: Injected[GreeterService]
) -> HttpResponse:
    name = request.GET.get("name", "World")
    return HttpResponse(greeter.greet(name))
views.py
from django.http import HttpRequest, HttpResponse
from wireup import Injected
from wireup.integration.django import inject

from myapp.services import AsyncGreeterService


@inject
async def greet(
    request: HttpRequest, greeter: Injected[AsyncGreeterService]
) -> HttpResponse:
    name = request.GET.get("name", "World")
    return HttpResponse(await greeter.agreet(name))
views.py
from django.http import HttpRequest, HttpResponse
from django.views import View
from wireup import Injected
from wireup.integration.django import inject

from myapp.services import GreeterService


class GreetingView(View):
    @inject
    def get(
        self,
        request: HttpRequest,
        greeter: Injected[GreeterService],
    ) -> HttpResponse:
        name = request.GET.get("name", "World")
        return HttpResponse(greeter.greet(name))

Django REST Framework

DRF handlers should use @inject explicitly.

drf_views.py
from rest_framework.decorators import api_view
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 wireup import Injected
from wireup.integration.django import inject

from myapp.services import GreeterService


@api_view(("GET",))
@inject
def drf_function_view(
    request: Request, greeter: Injected[GreeterService]
) -> Response:
    name = request.query_params.get("name", "World")
    return Response({"message": greeter.greet(name)})


class GreetingAPIView(APIView):
    @inject
    def get(
        self, request: Request, greeter: Injected[GreeterService]
    ) -> Response:
        name = request.query_params.get("name", "World")
        return Response({"message": greeter.greet(name)})


class GreetingViewSet(ViewSet):
    @inject
    def list(
        self, request: Request, greeter: Injected[GreeterService]
    ) -> Response:
        name = request.query_params.get("name", "World")
        return Response({"message": greeter.greet(name)})

Django Ninja

Ninja handlers should also use @inject explicitly.

ninja_views.py
from ninja import Router, Schema
from wireup import Injected
from wireup.integration.django import inject

from myapp.services import GreeterService


router = Router()


class ItemSchema(Schema):
    name: str
    price: float


@router.get("/greet")
@inject
def greet(request, name: str, greeter: Injected[GreeterService]):
    return {"greeting": greeter.greet(name)}


@router.post("/items")
@inject
def create_item(request, data: ItemSchema, greeter: Injected[GreeterService]):
    return {
        "name": data.name,
        "price": data.price,
        "message": greeter.greet(data.name),
    }

Forms and Model Methods

If the callable runs during a request, use @inject.

forms.py
from django import forms
from wireup import Injected
from wireup.integration.django import inject

from myapp.services import UserService


class UserRegistrationForm(forms.Form):
    username = forms.CharField()

    @inject
    def __init__(self, *args, user_service: Injected[UserService], **kwargs):
        super().__init__(*args, **kwargs)
        self.user_service = user_service

    def clean_username(self):
        username = self.cleaned_data["username"]
        if self.user_service.is_taken(username):
            raise forms.ValidationError("Username taken")
        return username

Request Object Injection

The current HttpRequest is available as a scoped dependency.

services/auth.py
from django.http import HttpRequest
from wireup import injectable


@injectable(lifetime="scoped")
class AuthService:
    def __init__(self, request: HttpRequest) -> None:
        self.request = request

Testing

See Django Testing for request-handler tests, async testing with AsyncClient, and dependency overrides.