Creating custom manage.py commands

For my recent project pyremote, I needed to run a script every night to remove old job postings from the database. I decided to implement it as a custom manage.py command so that I can easily run it from command line and add it to a nightly cron job on the server.

To create a custom command you need to add a management directory to your Django app. In there create another directory called commands and in that one add a Python file and call it the way you want the command to be called. In my case I called it purge_old_jobs.py:

pyremote/
    __init__.py
    management/
        commands/
            purge_old_jobs.py
    models.py
    views.py
    ...

The Python file you create must define a class called Command that inherits from BaseCommand. Create a method named handle in your Command class. The actual logic of the command goes in this method.

You can also define add_argument method where you specify any command line arguments you would like to pass to the custom command when you invoke it. These arguments are then available to the handle method in a dictionary called options.

# purge_old_jobs.py
import datetime
from django.core.management.base import BaseCommand
from pyremote.models import Job


class Command(BaseCommand):
    help = 'Cleans database from job posts older than the given number of days.'

    def add_arguments(self, parser):
        parser.add_argument('days', type=int, help='Retention period in days.')

    def handle(self, *args, **options):
        retention_period = datetime.timedelta(days=options['days'])
        expiry_date = datetime.date.today() - retention_period
        number_deleted, * _ = Job.objects.filter(creation_date__lt=expiry_date).delete()
        self.stdout.write(f'Number of expired jobs: {number_deleted}')

Now I can run this command to clean the database from jobs that are added to the page more than 30 days ago:

$ python manage.py purge_old_jobs 30

Subscribe via RSS