3👍
✅
Django doesn’t implement the ASGI Lifespan protocol.
Ref: https://github.com/django/django/pull/13636
Starlette does. FastAPI directly uses Starlette’s implementation of event handlers.
Here’s how you can achieve that with Django:
- Implement the ASGI Lifespan protocol in a subclass of Django’s
ASGIHandler
.
import django
from django.core.asgi import ASGIHandler
class MyASGIHandler(ASGIHandler):
def __init__(self):
super().__init__()
self.on_shutdown = []
async def __call__(self, scope, receive, send):
if scope['type'] == 'lifespan':
while True:
message = await receive()
if message['type'] == 'lifespan.startup':
# Do some startup here!
await send({'type': 'lifespan.startup.complete'})
elif message['type'] == 'lifespan.shutdown':
# Do some shutdown here!
await self.shutdown()
await send({'type': 'lifespan.shutdown.complete'})
return
await super().__call__(scope, receive, send)
async def shutdown(self):
for handler in self.on_shutdown:
if asyncio.iscoroutinefunction(handler):
await handler()
else:
handler()
def my_get_asgi_application():
django.setup(set_prefix=False)
return MyASGIHandler()
- Replace the
application
in asgi.py.
# application = get_asgi_application()
application = my_get_asgi_application()
- Implement a helper
get_client_session
to share the instance:
import asyncio
import aiohttp
from .asgi import application
CLIENT_SESSSION = None
_lock = asyncio.Lock()
async def get_client_session():
global CLIENT_SESSSION
async with _lock:
if not CLIENT_SESSSION:
CLIENT_SESSSION = aiohttp.ClientSession()
application.on_shutdown.append(CLIENT_SESSSION.close)
return CLIENT_SESSSION
Usage:
async def view(request: HttpRequest):
session = await get_client_session()
example_response = await session.get("https://example.com/")
response_text = await example_response.text()
return HttpResponse(response_text[:42], content_type="text/plain")
Source:stackexchange.com