Skip to main content

django-aiogram

PyPI Python CI License

Run aiogram next to Django: write handlers as ordinary Django app code, and send Telegram messages from anywhere in the project.

One container runs the bot. Every other process — web, Celery, a management command — hands the call to a broker and returns, so a request never waits on Telegram. Four transports can carry it, and BROKER says which:

                              ┌─ Redis list ────┐
  web, celery ──bot.send()──▶ ├─ Redis Streams ─┤ ──▶ start_tgbot ──▶ Telegram
                              ├─ RabbitMQ ──────┤
                              └─ Kafka ─────────┘
transport BROKER extra its own required settings
Redis list (default) django_aiogram.broker.redis_list.RedisListBroker [redis] —
Redis Streams django_aiogram.broker.redis_streams.RedisStreamsBroker [redis] REDIS_STREAM_KEY
RabbitMQ django_aiogram.broker.rabbitmq.RabbitMQBroker [rabbitmq] RABBITMQ_URL, RABBITMQ_QUEUE
Kafka django_aiogram.broker.kafka.KafkaBroker [kafka] KAFKA_BOOTSTRAP, KAFKA_TOPIC

Your code does not change with the row: the same bot.send(), handlers, event log and manage.py start_tgbot. What differs is what becomes of a message whose worker was killed mid-send, and what recovery is — a command, a clock, or the broker's own doing. Delivery compares them; each transport has a page of its own below.

Install

pip install 'django-aiogram[redis]'                 # Redis list, the default, or Redis Streams
pip install 'django-aiogram[rabbitmq,redis]'        # RabbitMQ
pip install 'django-aiogram[kafka,redis]'           # Kafka

One extra per transport, so a deployment downloads only the queue driver it uses. redis is in the other two lines for the FSM store, not the queue: FSM_STORAGE defaults to aiogram's Redis store, so a bot keeping chat state needs that driver whichever transport carries its messages, and FSM_STORAGE: 'memory' is what drops it.

Nothing is inferred from what happens to be installed: BROKER names the transport, and a base pip install django-aiogram imports and runs manage.py but carries no message. manage.py check names every extra that is missing, with the pip install line; Installation has the exceptions.

# settings.py
import os

INSTALLED_APPS = [..., 'django_aiogram']

TELEGRAM_BOT_DEFAULTS = {
    'TOKEN': os.environ.get('TELEGRAM_BOT_TOKEN', ''),
    # unset, BROKER resolves to RedisListBroker; the table above has the other three,
    # and each transport reads its own settings on top of these two
    'REDIS_URL': os.environ.get('REDIS_URL', ''),
}

Both may be empty: nothing connects or validates credentials at import time, so tests and migrations run without them. Requires Python 3.10–3.14, Django 5.2+ and aiogram 3.30+; each transport then pins its own driver and asks for its own server — Installation has both, per row.

Use it

# myapp/tg_router.py — imported automatically from every installed app
from aiogram import F, types

from django_aiogram import bot


@bot.message(F.text == '/start')
async def start(message: types.Message) -> None:
    await message.answer('hi')
# anywhere else in the project — `bots['support']` is the second bot, if there is one
from django_aiogram import bot, bots

bot.send(chat_id=CHAT_ID, text='Order approved')
python manage.py start_tgbot

More than one bot is a section each under TELEGRAM_BOTS, inheriting the defaults above and overriding what it names. One dispatcher and one handler tree serve all of them, bots configured alike share the connection and the consumer thread, and a queued message names the bot it is for wherever that bot has an identity — Multiple bots. Bots that arrive while it runs come from a provider, reconciled without a redeploy — Dynamic bots.

A router module, a call, and one process running the bot. That process gets Django's between-requests connection handling without having any requests — every update is bracketed with close_old_connections(), so a database that restarts under a long-running bot does not leave every handler raising InterfaceError until somebody notices. Nothing to configure; Deployment says what the healthcheck can and cannot see about it.

Everything else — rate limits, per-process opt-out, healthchecks — is configuration, documented rather than required. Webhook mode is the one alternative that also asks for a URL route: Webhook has the four steps.

Documentation

The documentation site is the documentation. Pages live in docs/wiki/, so they are reviewed in the same pull request as the code they describe and published from master.

Installation install, configure, run
Settings every setting, with defaults and check ids
Handlers routers, filters, FSM, the async ORM
Sending messages routes, keyboards, files, errors
Testing your suite without a broker, asserting what was queued
Multiple bots aliases, identities, what a set of bots shares and what it costs
Dynamic bots bots that arrive while it runs: providers, reconciliation, quarantine, leases
API the instance, its internals, and what stays public
Delivery how queued messages reach Telegram
Redis list the default transport: what it guarantees, and why the worker's name matters
Redis Streams the same server, a consumer group, and no worker identity to keep
RabbitMQ a broker that tracks its own consumers, and one thread per connection
Kafka offsets settle a prefix, ordering is per partition, a refusal rewinds
Webhook receiving updates over HTTP instead of polling
Scaling where polling stops, why a webhook costs nothing per bot, and what grows with the bots
Rate limits staying inside Telegram's published limits
Tokens where a bot's credential is kept, and rotating the key that wraps it
Admin configuring bots, profiles and queues, and the permission the token is behind
Deployment compose recipes, healthchecks, per-process opt-out
Logging the logger and its structured fields
Event log recording what the bot did to a table, and a signal to count it without one
Serialization what can be queued
Troubleshooting symptoms and their usual causes
Upgrading what each major release changed, and what you must do
AI assistants the brief to hand a coding agent

Upgrading from 3.x: the distribution is django-aiogram and the import path is django_aiogram, the driver is an extra you now name, and the event log has a table of its own. The upgrading page walks it in order, migrate included.

Contributing

CONTRIBUTING.md for the workflow, AGENTS.md for the same ground in the form coding agents read. Changes are in CHANGELOG.md; security reports go through SECURITY.md.

Metadata

Release files for django-aiogram 5.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-aiogram 5.0.0
File Size Uploaded
django_aiogram-5.0.0.tar.gz 1.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-aiogram 5.0.0
File Interpreter ABI Platform
django_aiogram-5.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.9 MB

Release files / django_aiogram-5.0.0.tar.gz

Download URL django_aiogram-5.0.0.tar.gz
Size 1.4 MB
Tags Source
SHA-256 checksum
How to use checksums
5a598a42686951a64217b25eea0f3b126a77c98f382c411be864b627c26fc426
BLAKE2b-256 checksum
How to use checksums
a1e89fac2dcba21b524a3104a1eb0ce435765198329766791307563acddb78c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / django_aiogram-5.0.0-py3-none-any.whl

Download URL django_aiogram-5.0.0-py3-none-any.whl
Size 511.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
57cef55184d235de6e3d2ff2ed7301df341ad0940b3540de554ece24e98b723b
BLAKE2b-256 checksum
How to use checksums
d44ac9a3b2329660ed84b881898d697abb457b866a0a26c3041efd107393b5cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release history Release notifications | RSS feed

5.1.0

2 release files

This release

5.0.0 This release

2 release files

4.1.0

2 release files

4.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page