Home › Cron Jobs with Django
Cron Jobs in Django
Three approaches: raw crontab, django-crontab or Celery Beat. Which one depends on your project's complexity and existing infrastructure.
Option 1: Raw Crontab with a Management Command
The simplest approach that works for any Django version. Create a management command and call it from cron. No extra dependencies, no magic.
Create myapp/management/commands/send_reports.py:
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Send weekly reports'
def handle(self, *args, **kwargs):
# your task logic here
self.stdout.write('Reports sent.')
Add to crontab:
0 8 * * 1 /home/user/project/venv/bin/python /home/user/project/manage.py send_reports >> /var/log/reports.log 2>&1
Use the virtualenv Python. The manage.py command loads Django's environment automatically,
so your models, settings and database are all available.
Option 2: django-crontab
Defines all your cron jobs in settings.py and installs them with one command.
Good for projects with multiple scheduled tasks - keeps everything in one place.
Package: django-crontab on PyPI.
Install:
pip install django-crontab
Add to INSTALLED_APPS:
INSTALLED_APPS = [
...
'django_crontab',
]
Define jobs in settings.py:
CRONJOBS = [
('0 2 * * *', 'myapp.cron.daily_backup'),
('*/15 * * * *', 'myapp.cron.process_queue', '>> /var/log/queue.log 2>&1'),
('0 9 * * 1', 'django.core.management.call_command', ['send_reports']),
]
Install and manage:
python manage.py crontab add # installs all CRONJOBS into the system crontab python manage.py crontab show # lists installed cron jobs python manage.py crontab remove # removes all installed jobs
Option 3: Celery Beat
If your project already uses Celery for async tasks, Celery Beat is the natural choice for periodic tasks. More setup, but you get distributed execution, retries and monitoring out of the box. Official docs: Celery Beat - Periodic Tasks.
pip install celery django-celery-beat
Define periodic tasks in settings.py:
from celery.schedules import crontab
CELERY_BEAT_SCHEDULE = {
'daily-backup': {
'task': 'myapp.tasks.daily_backup',
'schedule': crontab(hour=2, minute=0),
},
'process-queue': {
'task': 'myapp.tasks.process_queue',
'schedule': crontab(minute='*/15'),
},
'weekly-report': {
'task': 'myapp.tasks.send_report',
'schedule': crontab(hour=9, minute=0, day_of_week=1),
},
}
Run Celery Beat alongside your workers:
celery -A myproject beat -l info celery -A myproject worker -l info
Comparison
| Approach | Setup | Dependencies | Best for |
|---|---|---|---|
| Raw crontab | Minimal | None | Simple projects, 1-2 jobs |
| django-crontab | Easy | django-crontab | Multiple jobs, no Celery |
| Celery Beat | Complex | Celery + broker (Redis/RabbitMQ) | Production, distributed systems |
Start simple, scale when needed
Most Django projects start with a management command and a crontab entry, and that is enough for years. Only move to Celery Beat when you need distributed execution, per-job retries or dynamic schedule management from a database. django-crontab sits in between - it is a good middle ground if you want schedule definitions in code but do not need Celery's complexity.
Build the cron expression for your Django job
Both django-crontab and Celery Beat accept standard cron expressions. Use the generator and paste the result directly.