django-celery-beat
Store and manage Celery periodic task schedules in the Django ORM, editable from the Django admin.
Repository Health
Technical Analysis
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
DatabaseSchedulerclass registered as a Celery beat scheduler entry point (celery beat -S django) - Four schedule models —
IntervalSchedule,CrontabSchedule(with per-row timezone),SolarSchedule, andClockedSchedule— for one-off runs - A Django admin interface for
PeriodicTaskwith a searchable dropdown of registered Celery task names - Human-readable crontab descriptions (via
cron_descriptor) shown in the admin - Automatic change detection so
celery beatpicks 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.
Used by 4 apps in this directory
Baserow
No Code Platforms · Databases
Open-source no-code platform to build databases, apps, automations, and AI agents — self-hosted or cloud, with full data ownership.
MaxKB
AI Development · Knowledge Management
Build enterprise-grade AI agents with RAG, workflows & multi-modal support
SWIRL
Search · Databases · Data Engineering
Federated AI search and RAG across 100+ enterprise sources—no data extraction, no vector database required.
Weblate
Developer Tools
Continuous localization platform that commits translations directly into your version control system with full translator attribution.