Как работать с асинхронными запросами в Django?python-52

Введение в асинхронность в Django

Начиная с версии 3.0, Django добавил поддержку ASGI (Asynchronous Server Gateway Interface) и асинхронных представлений. Однако важно понимать ограничения:

  • ORM Django до версии 4.1 работала синхронно
  • Некоторые компоненты (кеширование, сессии) могут требовать синхронного доступа

1. Настройка асинхронного окружения

Установка зависимостей

pip install django channels daphne

Настройка asgi.py

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    # Дополнительные протоколы (WebSocket) можно добавить здесь
})

Изменение в settings.py

INSTALLED_APPS = [
    ...
    'channels',
]

ASGI_APPLICATION = 'myproject.asgi.application'

2. Создание асинхронных представлений

Базовое асинхронное view

from django.http import JsonResponse
from asgiref.sync import sync_to_async
import httpx

async def async_view(request):
    # Асинхронный HTTP-запрос
    async with httpx.AsyncClient() as client:
        response = await client.get('https://api.example.com/data')
        data = response.json()

    return JsonResponse(data)

Комбинирование с синхронным ORM

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

@sync_to_async
def get_users_count():
    return User.objects.count()

async def user_count_view(request):
    count = await get_users_count()
    return JsonResponse({'count': count})

3. Асинхронные запросы к БД

Нативная асинхронная ORM

from django.http import JsonResponse
from myapp.models import Product

async def product_list(request):
    products = await Product.objects.all().alist()
    return JsonResponse({'products': list(products)})

Транзакции

from django.db import transaction

async def create_product(request):
    async with transaction.atomic():
        product = await Product.objects.acreate(
            name="New Product",
            price=100.00
        )
    return JsonResponse({'id': product.id})

4. Параллельные запросы

Использование asyncio.gather

import asyncio
import httpx

async def fetch_data(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

async def multiple_requests_view(request):
    urls = [
        'https://api.example.com/data1',
        'https://api.example.com/data2'
    ]

    tasks = [fetch_data(url) for url in urls]
    responses = await asyncio.gather(*tasks)

    data = [resp.json() for resp in responses]
    return JsonResponse({'results': data})

5. Middleware для асинхронных запросов

Асинхронное middleware

async def async_middleware(get_response):
    async def middleware(request):
        # Предобработка запроса
        print("Async before view")

        response = await get_response(request)

        # Постобработка ответа
        print("Async after view")
        return response

    return middleware

6. Тестирование асинхронных представлений

Асинхронные тесты

from django.test import TestCase
from httpx import AsyncClient

class AsyncTestCase(TestCase):
    async def test_async_view(self):
        client = AsyncClient()
        response = await client.get('/async-url/')
        self.assertEqual(response.status_code, 200)

Ограничения и рекомендации

  1. Смешивание синхронного и асинхронного кода:

    • Используйте sync_to_async для синхронного кода
    • Избегайте "эффекта радуги" (частого переключения)
  2. Производительность:

    • Асинхронность полезна для I/O-bound операций
    • Не даёт преимуществ для CPU-bound задач
  3. Базы данных:

    • Для PostgreSQL используйте django.db.backends.postgresql_psycopg2 с 'DISABLE_SERVER_SIDE_CURSORS': True
    • Проверьте поддержку асинхронности вашим драйвером БД

Резюмируем

  1. Django поддерживает асинхронность начиная с версии 3.0, но полная поддержка ORM появилась в 4.1+
  2. Для работы с асинхронностью необходимо:
    • Настроить ASGI-приложение
    • Использовать асинхронные views
    • Правильно работать с ORM
  3. Основные преимущества:
    • Эффективная обработка множества I/O-операций
    • Улучшенная производительность для внешних запросов
  4. Основные инструменты:
    • async/await синтаксис
    • httpx.AsyncClient для HTTP-запросов
    • asyncio.gather для параллельных операций

Для новых проектов с интенсивными I/O-операциями асинхронный Django — отличный выбор, но для legacy-кода требуется осторожное внедрение.