-
Notifications
You must be signed in to change notification settings - Fork 2
AI assistants
Coding agents integrate this package the way a person would — by reading the docs — and they get the same handful of things wrong, usually because 1.x material is still the first thing a search finds. This page is the brief to hand them.
Everything an assistant needs to wire the package into a Django project
correctly, short enough to sit in a system prompt or a CLAUDE.md /
AGENTS.md / .cursor/rules file:
Project uses django-redis-aiogram 3.x. Rules:
- Import the shared instance: `from django_redis_aiogram import bot`. Never
construct TelegramBot() per task or per request — that builds an event loop and
an HTTP session nothing closes.
- To send from anywhere (view, task, signal): `bot.send(chat_id=..., text=...)`.
It queues through Redis outside the bot container and calls Telegram directly
inside it. Pass another method by name: bot.send('send_photo', chat_id=..., photo=...).
Only Telegram API methods aiogram exposes are accepted.
- Handlers go in <app>/tg_router.py and are registered with decorators on the
shared bot: @bot.message(F.text), @bot.callback_query(...). They are ordinary
async Django code; use afirst()/sync_to_async for the ORM.
- Bot-wide defaults such as parse_mode belong in
TELEGRAM_BOT['DEFAULT_BOT_PROPERTIES'], not in every send call.
- Settings live in the TELEGRAM_BOT dict; scalars can come from
DJANGO_REDIS_AIOGRAM_<NAME> environment variables.
- The package is safe to import with no TOKEN and no Redis. Do not add
placeholder credentials to make imports work, and do not guard imports in
try/except.
- `from django_redis_aiogram import bot` loads aiogram (~900 ms), which is the
cost of sending and is paid once. Import it in the modules that send, not in a
package `__init__` that every process loads.
- Only the container running `manage.py start_tgbot` runs the bot. Do not set
DJANGO_REDIS_AIOGRAM_ENABLED=0 on web or Celery processes: it turns their
sends into no-ops and the messages are dropped.
- Queued payloads are JSON. Keep SERIALIZER='json'. Writing pickle takes BOTH
SERIALIZER='pickle' and ALLOW_PICKLE=True — the flag alone only lets the
reader accept pickle, so a payload JSON cannot describe is still refused at
the point it is queued. It is the escape hatch for exactly those payloads,
and turning it on means whoever can write to the Redis list can execute code
in the bot container, so do it only on a queue nothing untrusted can write to.
- A queued send cannot raise in the caller. Failures are logged by the worker.
Use bot.send_raw with RAISE_EXCEPTION only when the caller must see the error.
- `python manage.py check` validates the settings; treat its E0xx/W0xx output as
the spec.
- Run `python manage.py migrate` after upgrading. The package ships one table,
created whether or not you turn the event log on.
- bot.send() returns a correlation id. Store it next to your own model if you
want to join your records to the event log later.
- The event log is off by default (TELEGRAM_BOT['EVENT_LOG']). Turning it on
needs a retention job — `manage.py tgbot_prune_events` — or the table grows
without bound. Message bodies are not stored unless EVENT_LOG_PAYLOAD='full',
which is a personal-data decision, not a verbosity one.
Add a notification. "In orders/views.py, notify the reviewer over Telegram
when an order is approved. Use bot.send from django_redis_aiogram so the
request does not wait on Telegram, and add a test that asserts the message was
queued — see the Testing page of the django-redis-aiogram wiki for the fakeredis
recipe."
Add a handler. "Add support/tg_router.py with a /status command that
answers with the caller's open ticket count. Register it with @bot.message
from django_redis_aiogram, keep the ORM access async, and do not touch
INSTALLED_APPS — autodiscover imports tg_router from every installed app."
Set up the containers. "Add a telegram_bot service to
docker-compose.yml running python manage.py start_tgbot, restarting always,
depending on redis, sharing the same image and .env as back. Leave
DJANGO_REDIS_AIOGRAM_ENABLED unset on the other services — they queue
messages."
Turn on the event log. "Run manage.py migrate first, then enable
TELEGRAM_BOT['EVENT_LOG'] in django-redis-aiogram — a process that starts
recording before the table exists drops everything it records until someone
notices. Then set EVENT_LOG_RETENTION_DAYS and schedule
manage.py tgbot_prune_events daily. Leave EVENT_LOG_PAYLOAD at its default
so message bodies stay out of the table, and grant support only
view_telegramevent." See Event-log.
Migrate an older project. "This project imports telegram_bot, which
django-redis-aiogram 3.0 removed. Move it to django_redis_aiogram 3.x
following the wiki's Upgrading page: rename it in INSTALLED_APPS, replace the
imports, move parse_mode into DEFAULT_BOT_PROPERTIES, drop the placeholder
token from settings, and use bot.router instead of bot._router." See
Upgrading.
Debug delivery. "Messages are queued but never arrive. Check in this order:
is the start_tgbot container running and is ENABLED true there, does
redis-cli -n <db> llen TELEGRAM_BOT_MESSAGE grow, and what does the
django_redis_aiogram logger say. The wiki's Troubleshooting page lists the
causes per symptom."
Each of these has been seen in real integrations, and each is a 1.x habit:
| Mistake | Why it happens | What to do instead |
|---|---|---|
A placeholder TOKEN in settings so imports work |
1.x built the bot at import time and crashed without one | Nothing. Since 2.0 it imports fine with no credentials |
parse_mode in every send call |
1.x had no other way |
DEFAULT_BOT_PROPERTIES once |
DJANGO_REDIS_AIOGRAM_ENABLED=0 on web and Celery |
it reads like "do not run the bot here" | Leave it unset; only start_tgbot runs the bot |
TelegramBot() inside a task |
the shared instance looks stateful | Import bot
|
bot._router |
it was private for a long time | bot.router |
try/except around the import |
defensive habit from the crashing version | Import it plainly |
| Expecting a queued send to raise | the call looks synchronous | The worker logs it; use send_raw if the caller must know |
SERIALIZER: 'pickle' "for keyboards" |
true in 1.0.4, false since aiogram 3 | JSON round-trips keyboards, media and files |
AGENTS.md in the repository root is the brief for that: layout, the commands
CI runs, and the invariants that have dedicated tests. Anything an agent changes
here needs a test that fails when the change is reverted.
Getting started
Running it
Reference