Telegram Bot webhook Django REST Framework – это современный и удобный способ интегрировать бота Telegram с backend‑приложением на Django. В первых 100 словах статей вы узнаете, как быстро настроить endpoint, который принимает обновления от Bot API, обрабатывает команды асинхронно через Celery и гарантирует доставку сообщений даже в случае сбоев, используя retries. Это ключевой подход для тех, кто хочет обеспечить надёжную связь между пользователями Telegram и своим веб‑сервисом.
Разбор задачи
В большинстве проектов взаимодействие с Telegram осуществляется через polling, но это медленно и не масштабируемо. Webhook позволяет Telegram сразу отправлять POST‑запросы на ваш сервер, когда приходит новое сообщение. Однако для стабильной работы webhook‑endpoint необходимо: 1) гарантировать, что запросы принимаются без ошибок; 2) обрабатывать команды без блокировки основного потока; 3) повторять попытки при временных сбоях. Django REST Framework (DRF) предоставляет удобный инструментарий для создания API‑пунктов, а Celery позволяет выполнять долгие задачи в фоне и реализовать механизм retries. В этой статье мы покажем, как интегрировать все эти компоненты шаг за шагом.
Пошаговое решение
Шаг 1: Создайте Django‑приложение и включите DRF. Добавьте в urls.py путь /telegram/webhook/. Шаг 2: Реализуйте ViewSet, который принимает JSON‑payload от Telegram и сохраняет обновления в модели Update. Шаг 3: Настройте Celery worker, чтобы обрабатывать команды из очереди. Внутри задачи используйте retry‑логики Celery, чтобы при ошибке 502 повторить попытку несколько раз. Шаг 4: Зарегистрируйте webhook в Bot API, указав URL вашего endpoint и SSL‑сертификат. После этого Telegram будет автоматически отправлять обновления, которые DRF будет принимать, а Celery – выполнять асинхронные действия.
Рабочий код
# views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.core.exceptions import PermissionDenied
from rest_framework.response import Response
from rest_framework.views import APIView
from .tasks import process_update
from .serializers import UpdateSerializer
@csrf_exempt
class TelegramWebhook(APIView):
authentication_classes = [] # webhook не требует auth
permission_classes = []
def post(self, request, *args, **kwargs):
# Проверяем токен, чтобы не принимать чужие запросы
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != settings.TG_WEBHOOK_SECRET:
raise PermissionDenied
# Сериализуем payload
serializer = UpdateSerializer(data=request.data)
if serializer.is_valid():
# Асинхронно отправляем задачу в Celery
process_update.delay(serializer.data)
return Response(status=200)
return Response(serializer.errors, status=400)
# tasks.py (Celery)
from celery import shared_task
from .bot import bot
@shared_task(bind=True, max_retries=5, default_retry_delay=10)
def process_update(self, update_data):
try:
bot.process_new_updates([update_data])
except Exception as exc:
# При ошибке повторяем попытку
raise self.retry(exc=exc)
# bot.py
import telegram
bot = telegram.Bot(token=settings.TG_BOT_TOKEN)
# Пример простого обработчика
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, "Привет! Я бот на Django.")
Типичные ошибки
- ❌ Не отключён CSRF: приводит к 403 при запросе.
- ❌ Неправильный URL webhook: Telegram не может доставить обновления.
- ❌ Не проверяется секретный токен: открытая точка входа.
- ❌ Celery не запущен: сообщения обрабатываются в основном процессе, блокируя webhook.
- ❌ Неправильная сериализация: payload не проходит валидацию, возвращает 400.
FAQ
Как быстро проверить, что webhook работает?
В консоли отправьте тестовый update через curl: curl -X POST -H "Content-Type: application/json" -d '{"update_id": 1, "message": {"chat": {"id": 123}, "text": "/start"}}' https://your-domain.com/telegram/webhook/. Если бот ответит, всё настроено.
Почему Celery не обрабатывает задачи?
Проверьте, что worker запущен и подключён к тому же брокеру. В логах должно быть сообщение о получении задачи. Если worker не видит очередь, убедитесь, что переменная CELERY_BROKER_URL совпадает.
Как повысить надёжность при ошибках?
В Celery используйте max_retries и default_retry_delay. Добавьте логирование в process_update и храните неудачные payload в базе для последующего анализа.
Заключение
Бот на Django + DRF + Celery готов к работе. Следуйте чек‑листу:
- ✅ Установлен и настроен Celery.
- ✅ Секретный токен webhook проверяется.
- ✅ CSRF отключён для webhook‑вью.
- ✅ Webhook URL подтверждён в BotFather.
- ✅ Задачи обрабатываются в фоне, без блокировки API.
- ✅ Добавлены retry‑логика и логирование ошибок.
