Some of the tasks for my website are recurring and need to be executed on a daily or hourly basis. This can be done by using a crontab, but each of them requires a different configuration and I prefer to keep the cron definitions part of the code.

Therefor, I settled on a different approach using apscheduler.

The way I tend to start it is by starting to define the jobs in a jobs module under each application package:

blog/jobs.py

from django.core import management
 
def daily_db_backup():
print('---> Making datababase backup')
management.call_command('dbbackup')
print('---> Finished datababase backup')
 
def hourly_project_refresh():
# refresh the project list

Each application can easily have it's own jobs module.

Then, under the main application, I create a command which can be used to run them:

core/management/commands/run_cronjobs

from django.core.management.base import BaseCommand
 
from apscheduler.schedulers.blocking import BlockingScheduler
 
import blog.jobs as blog_jobs
 
class Command(BaseCommand):
 
help = 'Runs the cronjobs'
 
def handle(self, *args, **options):
self._log_info("Configuring jobs")
scheduler = BlockingScheduler()
scheduler.add_job(blog_jobs.hourly_project_refresh, 'cron', minute='0', hour='*', day='*', week='*', month='*')
scheduler.add_job(blog_jobs.daily_db_backup, 'cron', minute='0', hour='1', day='*', week='*', month='*')
self._log_info("Running scheduler")
try:
scheduler.start()
except KeyboardInterrupt:
return
 
def _log_info(self, *msg):
full_msg = ' '.join(msg)
self.stdout.write(self.style.SUCCESS(full_msg))

You can then run the following command to have the cronjobs processed (in my case, I'm running them with supervisord):

$ ./manage.py run_cronjobs