#django #python

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

1from django.core import management
2
3def daily_db_backup():
4    print('---> Making datababase backup')
5    management.call_command('dbbackup')
6    print('---> Finished datababase backup')
7
8def hourly_project_refresh():
9    # 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

 1from django.core.management.base import BaseCommand
 2
 3from apscheduler.schedulers.blocking import BlockingScheduler
 4
 5import blog.jobs as blog_jobs
 6
 7class Command(BaseCommand):
 8
 9    help = 'Runs the cronjobs'
10
11    def handle(self, *args, **options):
12        self._log_info("Configuring jobs")
13        scheduler = BlockingScheduler()
14        scheduler.add_job(blog_jobs.hourly_project_refresh, 'cron', minute='0', hour='*', day='*', week='*', month='*')
15        scheduler.add_job(blog_jobs.daily_db_backup, 'cron', minute='0', hour='1', day='*', week='*', month='*')
16        self._log_info("Running scheduler")
17        try:
18            scheduler.start()
19        except KeyboardInterrupt:
20            return
21
22    def _log_info(self, *msg):
23        full_msg = ' '.join(msg)
24        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):

1$ ./manage.py run_cronjobs