Django Models and cron
May 23, 2012, 1:26 p.m.

I am currently working on a project where we wish to collect large amounts of data and store it in a MySQL database using Django. Django is a pleasure to work with, however, I ran into some difficulties when I wanted to run a database population script as a cron job.

The problem is that it is not possible (without modifications) to run scripts on Django Model objects directly from the command line and I was getting this error:

ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined

Lots of googling led me towards a solution. This article sheds some light on the issue, but the solution of setting the DJANGO_SETTINGS_MODULE and PYTHONPATH inside the crontab never worked for me.

Finally, I stumbled upon my solution: Custom django-admin commands! This is a brilliant Django feature that lets you extend the manage.py commands. By using this solution it is possible to run scripts on your Django model from the command line without any modifications.

The way to implement custom management commands is simple. You create a folder called management inside your app and create an __init__.py file inside it. Then you create another folder inside the management folder called commands and once again create an __init__.py file inside it. Now any script you place inside the commands folder will become a custom command -- unless the filename is prefixed with an underscore.

The structure should look like this:

-- app
    - __init__.py
    -- management
        - __init__.py
        -- commands
            - __init__.py
            - custom_command.py

You can place any number of python scripts inside the commands folder. The name of the script will be the name of the custom command. All there is left to do now is to put some code in custom_command.py. We need to create a Command class that extends BaseCommand. It could look something like this:

# content of custom_command.py
from django.core.management.base import BaseCommand
from app.models import Car

class Command(BaseCommand):
    help = 'Creates a new car'

    def handle(self, *args, **options):
        car = Car()
        car.save()

Now you can run a cron job that creates a car every 5 minutes!

*/5 * * * * python /path/to/app/manage.py custom_command

This example is of course very simplistic. Follow the link to the documentation to see how to do more, e.g. how to handle command line arguments.

Comments