← Назад к вопросам

В чём отличия между Django (и Django REST Framework) и асинхронными фреймворками, такими как FastAPI, AIOHTTP и Tornado?

2.0 Middle🔥 201 комментариев
#Django#FastAPI и Flask#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отличия Django / DRF от асинхронных фреймворков

Это критически важный вопрос о современной архитектуре веб-приложений. Выбор между этими подходами влияет на производительность, масштабируемость и сложность разработки.

Django / Django REST Framework

Django и DRF — это синхронные фреймворки, основанные на потоках (thread-based). Каждый запрос обрабатывается отдельным потоком из пула.

# Django: синхронный вид
from django.views import View
from django.http import JsonResponse
from django.db import models

class UserView(View):
    def get(self, request, user_id):
        # Этот код выполняется в отдельном потоке
        user = User.objects.get(id=user_id)  # ← Синхронный запрос в БД
        
        # Пока ждём БД, поток занят
        time.sleep(2)  # ← Блокирует поток
        
        return JsonResponse({"user": user.name})

# Django REST Framework
from rest_framework.views import APIView
from rest_framework.response import Response

class UserAPIView(APIView):
    def get(self, request, user_id):
        user = User.objects.get(id=user_id)  # ← Синхронный ORM
        serializer = UserSerializer(user)
        return Response(serializer.data)

Как это работает

1000 запросов
↓
Web-сервер (Gunicorn с 4 рабочими потоками)
├── Поток 1: обрабатывает запрос 1, ждёт БД (2 сек)
├── Поток 2: обрабатывает запрос 2, ждёт БД (2 сек)
├── Поток 3: обрабатывает запрос 3, ждёт БД (2 сек)
└── Поток 4: обрабатывает запрос 4, ждёт БД (2 сек)
↓
(Остальные 996 запросов ждут в очереди...)

FastAPI (Асинхронный)

FastAPI — асинхронный фреймворк на базе ASGI, использует async/await. Один процесс обрабатывает тысячи запросов.

# FastAPI: асинхронный вид
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import AsyncSession

app = FastAPI()

@app.get("/users/{user_id}")
async def get_user(user_id: int, session: AsyncSession):
    # Этот код может быть приостановлен
    user = await session.get(User, user_id)  # ← Асинхронный запрос в БД
    
    # Пока ждём БД, поток освобождается для других запросов
    await asyncio.sleep(2)  # ← Не блокирует поток
    
    return {"user": user.name}

Как это работает

1000 запросов
↓
Web-сервер (Uvicorn с 1 процессом)
├── Event Loop обрабатывает все 1000 запросов одновременно
│   ├── Запрос 1: ждёт БД → переключается на запрос 2
│   ├── Запрос 2: ждёт БД → переключается на запрос 3
│   └── ... и так далее
↓
Все запросы обрабатываются за ~2 сек (вместо 500 сек)

Основные различия

ПараметрDjango/DRFFastAPIAIOHTTPTornado
МодельСинхронная (потоки)Асинхронная (event loop)АсинхроннаяАсинхронная
ASGI/WSGIWSGIASGIASGIСвой протокол
Async поддержкаОграниченная (Django 3.1+)ПолнаяПолнаяПолная
ORMDjango ORM (синхронный)SQLAlchemy asyncСвой или внешнийSQLAlchemy async
Скорость запускаБыстроБыстроБыстроБыстро
ПроизводительностьСредняя (I/O)ВысокаяВысокаяВысокая
Потребление памятиВысокое (потоки)НизкоеНизкоеНизкое
ПростотаОчень простоПростоСреднеСредне
Батарейки в комплектеМного (auth, admin, migrations)Мало (fastapi-users, alembic)МалоМало
СообществоОгромноеРастёт быстроСреднееСреднее
ДокументацияОтличнаяОтличнаяХорошаяХорошая
МасштабируемостьПлохая (нужны потоки)ОтличнаяОтличнаяОтличная

Сравнение производительности

# Тест: 1000 запросов к API, которая делает запрос в БД (1 сек)

# Django с 4 потоками Gunicorn:
# 1000 запросов ÷ 4 потока × 1 сек = 250 секунд

# FastAPI с 1 процессом Uvicorn:
# 1000 запросов (параллельно) × 1 сек = ~1 сек
# Разница: 250x быстрее!

Практический пример: запросы к внешнему API

Django (ПЛОХО - синхронно)

import requests
from django.views import View
from django.http import JsonResponse

class ExternalDataView(View):
    def get(self, request):
        # Каждый запрос блокирует поток на ~2 сек
        data1 = requests.get("https://api1.com/data").json()  # 2 сек
        data2 = requests.get("https://api2.com/data").json()  # 2 сек
        data3 = requests.get("https://api3.com/data").json()  # 2 сек
        # Всего: 6 секунд (последовательно)
        
        return JsonResponse({
            "data1": data1,
            "data2": data2,
            "data3": data3,
        })

# Для N параллельных запросов нужно N потоков!
# 100 запросов = 100 потоков × 8 МБ = 800 МБ памяти

FastAPI (ХОРОШО - асинхронно)

import httpx
from fastapi import FastAPI

app = FastAPI()

@app.get("/data")
async def get_data():
    async with httpx.AsyncClient() as client:
        # Все 3 запроса выполняются параллельно
        results = await asyncio.gather(
            client.get("https://api1.com/data"),
            client.get("https://api2.com/data"),
            client.get("https://api3.com/data"),
        )
        # Всего: ~2 сек (параллельно!)
        
        return {
            "data1": results[0].json(),
            "data2": results[1].json(),
            "data3": results[2].json(),
        }

# Для N параллельных запросов нужна 1 корутина!
# 100 запросов = 1 процесс × 50 МБ

AIOHTTP

AIOHTTP — асинхронный фреймворк, более низкоуровневый, чем FastAPI.

import aiohttp
from aiohttp import web

async def handle_request(request):
    async with aiohttp.ClientSession() as session:
        async with session.get("https://api.example.com/data") as resp:
            data = await resp.json()
            return web.json_response(data)

app = web.Application()
app.router.add_get("/data", handle_request)

if __name__ == "__main__":
    web.run_app(app)

Tornado

Tornado — один из первых асинхронных фреймворков в Python, хорош для WebSocket.

import tornado.ioloop
import tornado.web
import tornado.httpclient

class MainHandler(tornado.web.RequestHandler):
    async def get(self):
        client = tornado.httpclient.AsyncHTTPClient()
        response = await client.fetch("https://api.example.com/data")
        self.write({"data": response.body})

def make_app():
    return tornado.web.Application([
        (r"/data", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8000)
    tornado.ioloop.IOLoop.current().start()

Когда использовать Django/DRF?

Используй Django/DRF, если:

  • Традиционное веб-приложение (с шаблонами)
  • Мало параллельных I/O операций
  • Нужны встроенные функции (auth, admin, migrations)
  • Нужно быстро разработать MVP
  • Команда опытна в Django
# Идеально подходит
from django.contrib.auth.decorators import login_required
from django.db import models

class BlogPost(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()

@login_required
def view_post(request, post_id):
    post = BlogPost.objects.get(id=post_id)  # Встроенная авторизация
    return render(request, "post.html", {"post": post})

Когда использовать FastAPI?

Используй FastAPI, если:

  • Разрабатываешь API (REST или GraphQL)
  • Нужна высокая производительность
  • Много параллельных запросов (WebSocket, Server-Sent Events)
  • Новый проект (можешь учиться на лучших практиках)
  • SPA фронтенд (React, Vue, Next.js)
# Идеально подходит
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Echo: {data}")

Можно ли использовать async в Django?

Да, но сложно! Django 3.1+ поддерживает async views, но:

  • ORM всё ещё синхронный (Django 4.1 добавил частичную поддержку)
  • Нужно использовать async_to_sync() / sync_to_async()
  • Меньше документации и примеров
# Django async view (не рекомендуется)
from django.views import View
from asgiref.sync import sync_to_async

class AsyncUserView(View):
    async def get(self, request):
        # ORM синхронный, нужно обёртка
        user = await sync_to_async(User.objects.get)(id=1)
        return JsonResponse({"user": user.name})

Миграция с Django на FastAPI

# Типичный путь:
# 1. FastAPI для API
# 2. Django только для админки и статики
# 3. Полный переход на FastAPI

# Структура проекта
project/
├── api/                # FastAPI (новое)
│   ├── main.py
│   └── routes/
└── admin/              # Django (старое)
    ├── manage.py
    └── views.py

Производительность на примере обработки изображений

# Django (синхронно)
def process_images(request):
    for i in range(100):
        image = Image.open(f"image_{i}.jpg")
        image.filter(ImageFilter.BLUR)  # 0.1 сек за image
    # Всего: 10 секунд (поток занят)
    return JsonResponse({"status": "done"})

# FastAPI (асинхронно)
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=4)

@app.post("/process-images")
async def process_images():
    def process_image(i):
        image = Image.open(f"image_{i}.jpg")
        return image.filter(ImageFilter.BLUR)
    
    # Обрабатываем 4 изображения одновременно
    results = await asyncio.gather(*[
        asyncio.get_event_loop().run_in_executor(
            executor, process_image, i
        )
        for i in range(100)
    ])
    # Всего: ~2.5 сек (параллельно 4 потоками, но в главном event loop)
    return {"status": "done"}

Итоговый вывод

ВыбирайЕсли
Django/DRFТрадиционное веб-приложение, MPA, встроенные батарейки
FastAPIAPI, SPA, высокая производительность, микросервисы
AIOHTTPLow-level async контроль, специальные требования
TornadoReal-time приложения, WebSocket, очень нагруженные

Современный тренд:

  • Новые проекты → FastAPI
  • Существующие → Django (может быть постепенная миграция)
  • Высоконагруженные → FastAPI или AIOHTTP

Ключевой момент: Асинхронные фреймворки дают 100-1000x выигрыш в производительности для I/O-bound приложений!

В чём отличия между Django (и Django REST Framework) и асинхронными фреймворками, такими как FastAPI, AIOHTTP и Tornado? | PrepBro