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

ApproachSetupDependenciesBest 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.