django-celery-beat

Store and manage Celery periodic task schedules in the Django ORM, editable from the Django admin.

Library
PyPI
v2.9.0
1,952stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
86/100Excellent
Development Activity88
Maintenance68
Community88
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture82
Code Quality85
Innovation78
Learning Curve75

django-celery-beat is a Celery scheduler backend that stores periodic task schedules as rows in the Django database instead of a local shelve file. It registers a DatabaseScheduler via Celery’s celery.beat_schedulers entry point, so running celery beat -S django reads and writes schedules from your Django app’s database, and any process (including the Django admin) can create, edit, or disable periodic tasks without redeploying code.

Schedules come in four flavors — fixed interval, crontab (with per-schedule IANA timezones), solar (sunrise/sunset events for a latitude/longitude), and one-off clocked runs — each modeled as its own table (IntervalSchedule, CrontabSchedule, SolarSchedule, ClockedSchedule) and surfaced through a PeriodicTask model with a full Django admin interface, including a task-name dropdown populated from the running Celery app’s registered tasks. A lightweight PeriodicTasks change-counter model lets the beat process detect schedule edits made by other processes without needing a restart.

What You Get

  • A DatabaseScheduler class registered as a Celery beat scheduler entry point (celery beat -S django)
  • Four schedule models — IntervalSchedule, CrontabSchedule (with per-row timezone), SolarSchedule, and ClockedSchedule — for one-off runs
  • A Django admin interface for PeriodicTask with a searchable dropdown of registered Celery task names
  • Human-readable crontab descriptions (via cron_descriptor) shown in the admin
  • Automatic change detection so celery beat picks up schedule edits made by any process without restarting

Common Use Cases

  • Letting ops or support staff pause, retime, or disable a periodic task from the Django admin without a deploy
  • Creating per-tenant periodic tasks programmatically in a multi-tenant SaaS (one scheduled job per customer row)
  • Scheduling jobs relative to sunrise/sunset for a given location via SolarSchedule
  • Scheduling a task to run exactly once at a specific future timestamp via ClockedSchedule

Under The Hood

Architecture The package is a standard installable Django app (django_celery_beat) whose entry point is registered via setup.py’s celery.beat_schedulers hook pointing at schedulers.DatabaseScheduler, which subclasses Celery’s beat.Scheduler and wraps each database row as a ModelEntry (a celery.beat.ScheduleEntry subclass) that lazily resolves one of four schedule types (IntervalSchedule, CrontabSchedule, SolarSchedule, ClockedSchedule, all defined in models.py) into a Celery-native schedule object. A separate PeriodicTasks model acts as a single-row change counter that the scheduler polls on a short interval to detect edits made outside the beat process itself (for example via the Django admin in admin.py, or bulk .update() calls followed by a manual PeriodicTasks.update_changed()), and signals.py wires Django’s post_save/post_delete on PeriodicTask to increment that counter automatically. Because every schedule-type resolution path and the change-detection polling both depend on that same counter row, it is the one abstraction the rest of the package is built around.

Tech Stack A pure Python package targeting Django 3.2 through 6.1 and Celery 5.3.x, with django-timezone-field for storing per-schedule IANA timezones, python-crontab and cron-descriptor for crontab parsing and human-readable text, and tzdata/backports.zoneinfo for older-Python zoneinfo support. It ships no separate build step beyond setuptools, is published to PyPI via a GitHub Actions workflow using PyPI trusted publishing (OIDC, no stored token), and is tested across the full Django/Python compatibility matrix with tox.

Code Quality An extensive unit test suite spans admin behavior, crontab parsing, model validation, and scheduler internals, including coverage of a documented naive-vs-aware timezone normalization edge case with an inline comment explaining the reasoning rather than leaving it unexplained. Linting is enforced through an extensive Ruff rule set (including security and complexity checks) with narrowly scoped per-file ignores rather than blanket suppressions, backed by pre-commit hooks. Error handling favors explicit logging-and-disable over silent failure — for example the scheduler catches missing-schedule and JSON-deserialization errors on a task entry, logs the problem, and disables just that one periodic task instead of crashing the whole beat process. CI runs the full test matrix plus a dedicated static-analysis workflow.

API Design The public surface is intentionally small and idiomatic Django: a handful of model classes usable via ordinary objects.create()/get_or_create() calls exactly as shown in the README, one entry-point string to wire into celery beat -S django, and no custom configuration DSL beyond adding the app to INSTALLED_APPS and running migrations. Getting started requires no bespoke settings class or config format — just a model, a migration, and a scheduler flag — though the admin’s task-name dropdown does depend on the Celery app already being importable at render time, a minor coupling worth knowing about going in.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search