Schedule Django Background Tasks using Systemd Timers

Schedule Django Background Tasks using Systemd Timers

Recently, I had to add a simple background task in a Wagtail site. There was a form that visitors needed to fill out and the data would be saved in the database. The owner wanted that data emailed to him in csv format every month. Simple enough.

I could use something like Celery or Django Q but this was a small server with 512MB of RAM and this was a once a month task, so, it warranted something simpler.

One thing that immediately came to mind is Cron. It’s nice and simple but since this Django project was deployed on Ubuntu 18.04, I decided to go with a Systemd timer instead. With timers, I get free logging using journald, it’s easier to run commands as any user, and you can run the command any time you want.

Don’t worry if this sounded gibberish to you, it’s quite simple once you see it. Let’s get to work.

In this post:

The management command

The task is a really simple management command . It basically took these steps:

  1. Filter for the Django model instances that were created 1 month from now.
  2. Turn them into csv.
  3. Email it to the owner as an attachment.

Very basic stuff really.

Setting up the service and timer

Systemd timers require a service and timer file in the /etc/systemd/system directory.

Here’s the service /etc/systemd/system/csv-mailer.service:

[Unit]
Description=Email csv to site owner

[Service]
User=django
WorkingDirectory=/opt/django
ExecStart=/opt/django/venv/bin/python manage.py mail_csv

[Install]
WantedBy=default.target

And the timer /etc/systemd/system/csv-mailer.timer

[Unit]
Description=Run the csv mailer every month

[Timer]
OnCalendar=monthly
Unit=csv-mailer.service
Persistent=true

[Install]
WantedBy=timers.target

Activate the timer with systemctl daemon-reload && systemctl enable csv-mailer.timer.

Because services can be started manually, you can test it out immediately with systemctl start csv-mailer.service.

Find out how the service is doing by inspecting the logs: journcalctl -u csv-mailer.service.

I also use timers for background tasks on some projects by running a management command that polls the database for changes and executes other commands if needed. They work marvelously for simple deployments.

Give them a try, you won’t regret it.