Install & Compatibility
Where this runs
tested against v0.7.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.000s · 67.2MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 3.6s · import 0.000s · 68MB
66MB installed
● package 66MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
default_app_config
✓ from django_apscheduler import default_app_config
✗ from django_apscheduler.jobstores import DjangoJobStore
To set up `django-apscheduler`, first add `django_apscheduler` to your `INSTALLED_APPS`. Then, create a custom Django management command (e.g., `your_project_name/management/commands/runapscheduler.py`) to initialize and start the scheduler with the `DjangoJobStore`. This approach is recommended to ensure a single scheduler instance runs in a dedicated process, avoiding duplicate job executions in multi-process web server environments. Finally, run `python manage.py migrate` and then execute your custom command, typically managed by a process supervisor like systemd or Supervisor.
import logging
from django.conf import settings
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
from django.core.management.base import BaseCommand
from django_apscheduler.jobstores import DjangoJobStore
from django_apscheduler.models import DjangoJobExecution
from django_apscheduler import util
logger = logging.getLogger(__name__)
def my_job():
# Your job processing logic here...
logger.info("My job is running!")
# The `close_old_connections` decorator ensures that database connections that have become
# unusable or are obsolete are closed before and after your job has run. You should use it
# to wrap any jobs that you schedule that access the Django database in any way.
@util.close_old_connections
def delete_old_job_executions(max_age=604_800):
"""This job deletes APScheduler job execution entries older than `max_age` from the database."""
logger.info(
"Deleting old job executions... (anything older than %s seconds)", max_age
)
DjangoJobExecution.objects.delete_old_job_executions(max_age)
class Command(BaseCommand):
help = "Runs APScheduler."
def handle(self, *args, **options):
scheduler = BlockingScheduler(timezone=settings.TIME_ZONE)
scheduler.add_jobstore(DjangoJobStore(), "default")
scheduler.add_job(
my_job,
trigger=CronTrigger(second="*/10"), # Every 10 seconds
id="my_job", # The `id` assigned to each job MUST be unique
max_instances=1,
replace_existing=True,
)
logger.info("Added job 'my_job'.")
scheduler.add_job(
delete_old_job_executions,
trigger=CronTrigger(day_of_week="mon", hour="00", minute="00"), # Midnight on Monday
id="delete_old_job_executions",
max_instances=1,
replace_existing=True,
)
logger.info(
"Added daily job: 'delete_old_job_executions'."
)
# Add a listener to log job executions and errors
# register_events(scheduler)
scheduler.start()
logger.info("Scheduler started. Press Ctrl+C to exit.")
# To run this, save it as `your_project_name/management/commands/runapscheduler.py`
# Then, in your Django settings.py, add 'django_apscheduler' to INSTALLED_APPS.
# Run migrations: `python manage.py migrate`
# Start the scheduler: `python manage.py runapscheduler` (preferably in a dedicated process)
Debug
Known issues
breakingVersion 0.7.0 dropped support for Python 3.8 and Django 3.2. Ensure your environment meets the new minimum requirements.fixUpgrade Python to 3.9+ and Django to 4.2+.
affects: 0.7.0+
gotchaRunning `django-apscheduler` within a multi-process web server (e.g., Gunicorn with multiple workers) can lead to jobs running multiple times or being missed, as APScheduler lacks inter-process synchronization. It does not support shared job stores across multiple active schedulers.fixRun the scheduler in a single, dedicated process using a custom Django management command (e.g., `python manage.py runapscheduler`), managed by a process supervisor like systemd or Supervisor. Do not start the scheduler directly in `apps.py`'s `ready()` method or `urls.py` if running with multiple web server workers. [1, 7, 8, 13, 16]
affects: All versions
deprecatedThe `@register_job` decorator was deprecated in favor of APScheduler's native `add_job()` method or `@scheduled_job` decorator.fixUse `scheduler.add_job()` or `@scheduled_job` instead of `@register_job` for scheduling tasks.
affects: 0.5.0+
gotchaJobs that access the Django database (ORM) can suffer from 'lost connection' errors or timeouts. Django's database connection management is typically designed for short-lived HTTP requests.fixApply the `@util.close_old_connections` decorator to any scheduled job function that interacts with the Django ORM. For persistent issues, consider implementing a database connection pooler (e.g., PgBouncer for PostgreSQL) as part of your deployment strategy. [8, 13]
affects: All versions
breakingAPScheduler 4.0 introduced significant architectural changes (e.g., new job store design, event brokers, new terminology). `django-apscheduler` versions prior to one explicitly stating APScheduler 4.0 compatibility may not work correctly with `APScheduler` 4.x.fixEnsure `django-apscheduler`'s `APScheduler` dependency is `<4.0` unless an explicit update to `django-apscheduler` for `APScheduler` 4.0+ is released. While v0.7.0 bumps dependencies, APScheduler 4.0 requires deep integration changes not just a version bump. [3, 7, 13, 14]
affects: < 0.7.0 (likely continues for future 3.x APScheduler versions compatible with django-apscheduler 0.7.0)
Upgrade
Version history
0.7.0latest on PyPI · released Sep 28, 2024
Audit
Dependencies
APSchedulerrequiredCore scheduling library. django-apscheduler provides a wrapper for it.
DjangorequiredWeb framework that django-apscheduler integrates with.