Как создать асинхронную функцию-представление (view) в Django

«Как создать асинхронную функцию-представление (view) в Django» — вопрос из категории Django, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Начиная с Django 3.1, можно создавать асинхронные представления (views), используя синтаксис async def. Это позволяет эффективно обрабатывать I/O-bound операции (например, HTTP-запросы к внешним API, работа с WebSocket) без блокировки потока.

Пример простого асинхронного представления:

import asyncio
from django.http import JsonResponse

async def my_async_view(request):
    # Имитация неблокирующей операции, например, запроса к API
    await asyncio.sleep(1)
    return JsonResponse({'status': 'ok', 'message': 'Completed async task'})

Ограничения и работа с ORM

Основное ограничение заключается в том, что ORM Django до версии 4.1 был полностью синхронным. Вызов синхронного кода ORM (например, User.objects.all()) внутри async def заблокирует event loop.

Для решения этой проблемы используется адаптер asgiref.sync.sync_to_async.

Пример асинхронного view с синхронным вызовом ORM:

from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
from django.http import JsonResponse

# Оборачиваем синхронный вызов ORM в асинхронную функцию
@sync_to_async
def get_user_count():
    return User.objects.count()

async def user_count_view(request):
    # Асинхронно ожидаем результат выполнения синхронного кода
    count = await get_user_count()
    return JsonResponse({'user_count': count})

Примечание: Начиная с Django 4.1, ORM получил частичную нативную поддержку асинхронных операций (например, aget, acreate, acount), что упрощает написание такого кода.