async def example_view(request) -> HttpResponse:
# The client is instanciated just once when the application starts,
# and closed when the server shuts down
httpx_client: httpx.AsyncClient = request.state["httpx_client"]
ASGIHandler
subclass that handles the ASGI Lifespan Protocol without affecting HTTP request handling.ClientSession
or an HTTPX AsyncClient
when your app starts, and close them properly when your app ends. This concept is similar to events in FastAPI.Python ^3.10 || ^3.11 || ^3.12 || ^3.13
and Django ^4.2 || ^5.0.3 || ^5.1
are supported. To install this package, run:
poetry add django-asgi-lifespan@latest
or
pip install --upgrade django-asgi-lifespan
Modify asgi.py
to use a ASGI Lifespan compatible handler.
from django_asgi_lifespan.asgi import get_asgi_application
django_application = get_asgi_application()
async def application(scope, receive, send):
if scope["type"] in {"http", "lifespan"}:
await django_application(scope, receive, send)
else:
raise NotImplementedError(
f"Unknown scope type {scope['type']}"
)
Add state middleware:
MIDDLEWARE = [
# ...
"django_asgi_lifespan.middleware.LifespanStateMiddleware",
# ...
]
Register async context manager:
from contextlib import asynccontextmanager
import httpx
from django_asgi_lifespan.types import LifespanManager
@asynccontextmanager
async def httpx_lifespan_manager() -> LifespanManager:
state = {
"httpx_client": httpx.AsyncClient()
}
try:
yield state
finally:
await state["httpx_client"].aclose()
from django.apps import AppConfig
from django_asgi_lifespan.register import register_lifespan_manager
from .context import (
httpx_lifespan_manager,
)
class ExampleAppConfig(AppConfig):
def ready(self):
register_lifespan_manager(
context_manager=httpx_lifespan_manager
)
Use some resource (in this case the HTTPX client) in views.
from http import HTTPStatus
import httpx
from django.http import HttpResponse
async def example_view(request) -> HttpResponse:
httpx_client: httpx.AsyncClient = request.state["httpx_client"]
await httpx_client.head("https://www.example.com/")
return HttpResponse(
"OK",
status=HTTPStatus.OK,
content_type="text/plain; charset=utf-8",
)
Run uvicorn:
uvicorn asgi:application --lifespan=on --port=8080