Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/illagrenan/django-asgi-lifespan
Django ASGI handler with Lifespan Protocol support.
https://github.com/illagrenan/django-asgi-lifespan
asgi asyncio django python
Last synced: about 6 hours ago
JSON representation
Django ASGI handler with Lifespan Protocol support.
- Host: GitHub
- URL: https://github.com/illagrenan/django-asgi-lifespan
- Owner: illagrenan
- License: mit
- Created: 2022-07-18T20:25:23.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-11-15T08:10:59.000Z (4 days ago)
- Last Synced: 2024-11-15T09:23:27.537Z (3 days ago)
- Topics: asgi, asyncio, django, python
- Language: Python
- Homepage: https://illagrenan.github.io/django-asgi-lifespan/
- Size: 2.12 MB
- Stars: 12
- Watchers: 3
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
Django ASGI Handler with Lifespan protocol support
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![pypi](https://img.shields.io/badge/code%20style-The%20Ruff%20Formatter-000000.svg)](https://docs.astral.sh/ruff/formatter/)
[![pypi](https://img.shields.io/pypi/v/django-asgi-lifespan.svg)](https://pypi.org/project/django-asgi-lifespan/)
[![Python version](https://img.shields.io/pypi/pyversions/django-asgi-lifespan.svg?logo=python&logoColor=white&label=python)](https://pypi.org/project/django-asgi-lifespan/)
![Supported Django](https://img.shields.io/badge/django%20versions-%5E4.2%20||%20%5E5.0.3-blue.svg?logo=django&logoColor=white)
[![Build Status](https://github.com/illagrenan/django-asgi-lifespan/actions/workflows/development.yml/badge.svg)](https://github.com/illagrenan/django-asgi-lifespan/actions/workflows/development.yml)
[![codecov](https://codecov.io/gh/illagrenan/django-asgi-lifespan/branch/main/graphs/badge.svg)](https://codecov.io/github/illagrenan/django-asgi-lifespan)* Documentation:
* PyPI:
* License: [MIT](https://choosealicense.com/licenses/mit/)## Main features
``` py hl_lines="4" linenums="1"
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"]
```* The package includes a Django `ASGIHandler` subclass that handles the [ASGI Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) without affecting HTTP request handling.
* [Startup](https://asgi.readthedocs.io/en/latest/specs/lifespan.html#startup-receive-event)
and [Shutdown](https://asgi.readthedocs.io/en/latest/specs/lifespan.html#shutdown-receive-event) Lifespan events are
converted to [Django signals](https://docs.djangoproject.com/en/4.0/topics/signals/).
* The package allows for awaiting on signal receivers. This means you can set up things like an [aiohttp `ClientSession`](https://docs.aiohttp.org/en/stable/client_reference.html) or an [HTTPX `AsyncClient`](https://www.python-httpx.org/async/) when your app starts, and close them properly when your app ends. This concept is similar to [events in FastAPI](https://fastapi.tiangolo.com/advanced/events/).## Quickstart
1. 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:
```console linenums="0"
poetry add django-asgi-lifespan@latest
```_or_
```console linenums="0"
pip install --upgrade django-asgi-lifespan
```2. Modify `asgi.py` to use a ASGI Lifespan compatible handler.
``` py title="asgi.py"
from django_asgi_lifespan.asgi import get_asgi_applicationdjango_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:
``` python hl_lines="3"
MIDDLEWARE = [
# ...
"django_asgi_lifespan.middleware.LifespanStateMiddleware",
# ...
]
```
4. Register [async context manager](https://docs.python.org/3/reference/datamodel.html#async-context-managers):``` py hl_lines="8-17" title="context.py"
from contextlib import asynccontextmanagerimport 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()
`````` py hl_lines="12-14" title="apps.py"
from django.apps import AppConfigfrom 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
)
```5. Use some resource (in this case the HTTPX client) in views.
``` py hl_lines="8" title="views.py"
from http import HTTPStatusimport httpx
from django.http import HttpResponseasync 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",
)
```6. Run uvicorn:
```console
uvicorn asgi:application --lifespan=on --port=8080
```