Найти в Дзене

Django 6.0 и фоновая магия: почему новый django.tasks — это не Celery, но шаг в будущее

Выход Django 6.0 стал событием сам по себе, но одно нововведение прошло тихо, хотя способно изменить подход к архитектуре проектов. Речь о новом модуле django.tasks — встроенном фреймворке фоновых задач. Не спешите радоваться слишком рано: это не замена Celery, Huey или Dramatiq. Django не научился запускать фоновые задачи сам — он просто предлагает унифицированный API, который должны реализовывать разные бэкенды очередей. Если Celery — это огромный и зубастый комбайн, то django.tasks — это минималистичная спецификация, которая решает давно наболевшую проблему: разный синтаксис для разных очередей. Теперь же Django предлагает единый язык общения с задачами. И это важно. Впервые за много лет фреймворк двинулся к стандартизации того, что раньше было дикой зоной. Новый модуль даёт две ключевые вещи: Но не даёт воркера. Это намеренно: Django создаёт API, а инфраструктуру вы выбираете сами. Фактически, Django говорит: «Мы стандартизируем задачи. Выберите подходящий backend — хоть Celery, хо
Оглавление

Выход Django 6.0 стал событием сам по себе, но одно нововведение прошло тихо, хотя способно изменить подход к архитектуре проектов. Речь о новом модуле django.tasks — встроенном фреймворке фоновых задач.

Не спешите радоваться слишком рано: это не замена Celery, Huey или Dramatiq. Django не научился запускать фоновые задачи сам — он просто предлагает унифицированный API, который должны реализовывать разные бэкенды очередей.

Если Celery — это огромный и зубастый комбайн, то django.tasks — это минималистичная спецификация, которая решает давно наболевшую проблему: разный синтаксис для разных очередей. Теперь же Django предлагает единый язык общения с задачами.

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

🔌 Что добавили в Django 6.0: минимальный API, максимум гибкости

Новый модуль даёт две ключевые вещи:

  • 🧩 декоратор @task, превращающий функцию в задачу
  • 🚚 метод enqueue, добавляющий задачу в очередь

Но не даёт воркера.

Это намеренно: Django создаёт API, а инфраструктуру вы выбираете сами.

Фактически, Django говорит:

«Мы стандартизируем задачи. Выберите подходящий backend — хоть Celery, хоть ваш собственный на Redis, хоть Postgres, хоть Kubernetes Jobs.»

Для больших команд — это огромный плюс: можно менять очередь, не трогая код приложения.

📬 Пример демонстрационного проекта: уведомления через ntfy.sh

Автор новости пошёл дальше и реализовал демо-бэкенд на базе БД, который умеет:

  • 🔁 ретраи
  • ⏳ экспоненциальный backoff
  • 📥 polling-воркер
  • 📡 отправку уведомлений через ntfy.sh

Это показывает, что даже простой бэкенд можно собрать буквально «на коленке».

Код таска выглядит почти невинно:

from django.tasks import task

@task
def send_notification(message: str, title: str | None):
...

Но ключевая деталь: функцию после декорирования уже нельзя вызвать напрямую — только через .enqueue().

Это жёсткая, но правильная защита от случайного выполнения задачи в потоке Django и от нарушения принципа изоляции фоновой логики.

🏗️ Что мне особенно понравилось: бэкенд на БД как инженерный эксперимент

Автор статьи делает то, что Django намеренно не делает: создаёт полноценную инфраструктуру.

Основа — модель Task:

  • 🗂️ приоритет
  • 🕒 run_after
  • 🧬 аргументы задачи
  • 🔁 attempt_count
  • 📌 состояние (READY, RUNNING, FAILED…)

Всё это превращает базу данных в простейшую очередь.

А затем — деление на:

  • 🧱 Task — сама задача
  • 🧹 Attempt — попытка выполнения
  • 🧯 Error — полная информация об исключении

Это даёт очень богатое представление о статусе задачи. Такой подход я вижу редко, но это именно то, чего не хватает Celery из коробки (out-of-the-box): прозрачной истории выполнения.

⚙️ Поллинг-воркер: примитивно, но надёжно

Воркера в Django нет, и автор создаёт свой.

Он делает очень простую вещь:

  • 👀 проверяет, есть ли доступные задачи
  • 📥 атомарно «захватывает» задачу (чтобы другой воркер её не забрал)
  • 🚀 выполняет её
  • 🧾 сохраняет результат
  • 🕙 если ошибка — планирует retry через backoff

И всё.

Но по сути это минимальный каркас для любых фоновых систем — от RabbitMQ до K8s Jobs.

🎄 Маленькие детали, которые меня зацепили

Несколько технических моментов, которые кажутся мелкими, но на деле — суперважны:

🧩 1. Декоратор @task запрещает прямой вызов

Это дисциплинирует кодовую базу.
В Celery эта проблема преследует проекты годами.

🪝 2. Retry реализуется на уровне бэкенда, а не Django

И Django честно признаёт: «Оркестрация — не наша зона».

🧩 3. Возможность takes_context=True

В задачу можно передать контекст выполнения:
количество попыток, состояние задачи и прочее.

Это открывает путь к очень сложной логике ретраев.

🪄 4. Django 6.0 добавил template partials

В демо это используется для обновления статуса задач через htmx. Мелочь, но усиливает ощущение целостной архитектуры.

🔮 Мой взгляд: django.tasks — это фундамент для большой эволюции

Я считаю появление django.tasks очень важным по трём причинам:

🔧 1. Стандартирование API

Разные очереди — один интерфейс.
Это давно назревало.

🚀 2. Django перестаёт избегать темы фоновых задач

Раньше фреймворк вообще предпочитал отмалчиваться, будто фоновые задачи — личное дело разработчика.

Теперь это официальная часть экосистемы.

🧱 3. Движение к экосистеме а-ля WSGI/ASGI

Django создаёт «базовый протокол», а дальше каждый пишет свои бэкенды.

Я уверен, что:

  • появятся новые task-бэкенды от крупных команд
  • Celery сделает адаптер
  • DRF добавит инструменты для мониторинга задач
  • появятся UI-панели и devtools для django.tasks

Пока это скромная альфа, но направление — правильное.

📎 Источники

🔗 Оригинальная статья
https://roam.be/notes/2025/a-first-look-at-djangos-new-background-tasks/

🔗 Документация Django tasks
https://docs.djangoproject.com/en/dev/topics/tasks/