Skip to content

Django ASGI Handler with Lifespan protocol support

License: MIT pypi pypi Python version Supported Django
Build Status codecov

Main features

1
2
3
4
async def example_view(request) -> HttpResponse:
    # The client is intanciated just once when the application starts,
    # and closed when the server shuts down
    httpx_client: httpx.AsyncClient = request.state["httpx_client"]

Quickstart

  1. Python ^3.10 || ^3.11 || ^3.12 and Django ^4.2 || ^5.0.3 are supported. To install this package run:

    poetry add django-asgi-lifespan@latest
    

    or

    pip install --upgrade django-asgi-lifespan
    
  2. Modify asgi.py to use a ASGI Lifespan compatible handler.

    asgi.py
    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']}"
            )
    
  3. Add state middleware:

    1
    2
    3
    4
    5
    MIDDLEWARE = [
        # ...
        "django_asgi_lifespan.middleware.LifespanStateMiddleware",
        # ...
    ]
    
    4. Register async context manager:

    context.py
    from contextlib import asynccontextmanager
    
    import httpx
    
    from django_asgi_lifespan.types import State
    
    
    @asynccontextmanager
    async def httpx_lifespan_manager() -> State:
        state = {
            "httpx_client": httpx.AsyncClient()
        }
    
        try:
            yield state
        finally:
            await state["httpx_client"].aclose()
    
    apps.py
    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
            )
    
  4. Use some resource (in this case the HTTPX client) in views.

    views.py
    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",
        )
    
  5. Run uvicorn:

    uvicorn asgi:application --lifespan=on --port=8080