A simple how-to for Django Cron jobs
Running regular timed cron functions for your Django site can be extremely useful, but it might be daunting for newbies (like it was for me!) - here's some simple tips.
If you're not sure what a cron job is, it's like a regular task manager, and you can give it simple commands like "do this job every Monday at 2.03am". It's often used for housekeeping tasks like backups, or regular cleaning of a database, but you can also use it for regular email sending.
You're going to:
- Figure out what your cron job will do, and when
- Create a Django management command function (eg. ./manage.py syncdb is a management command)
- Create a cronjob to trigger this function regularly
We'll assume that you're going to do (1) by yourself, and focus just on the technical aspects.
Create a custom Django management command
Management commands are things that you use regularly, like python manage.py runserver or python manage.py syncdb - many newbies don't know, but you can pretty easily create your own custom Django commands that work in exactly the same way.
What's the benefit of this? You'll see later, but it means you can run your Django function from cron without all the hassle of importing your settings, templates or other system tools (because they're already imported as part of your project's manage.py command.
So, first steps - inside your app, create a new folder called 'management' and inside that, a folder called 'commands'. Inside each of those folders, create an empty file called "__init__.py" - this lets Python know that this is a folder with Python code inside. It should look like this:
your_project/
your_app/
management/
__init__.py
commands/
__init__.py
Write the Django function you want to run
So now, inside the 'commands' folder you just created, make a new file and call it whatever you like. Make sure the ending is .py - for example, call it "send_newsletter.py" or "delete_old_comments.py". Give it a name that is descriptive, because you'll be running it from the command line later.
Open that file to edit it. You can write any normal Python/Django code in here, just like your views functions. However, there's some specific conventions you must apply for these custom commands.
# you MUST import the management classes like this:
from django.core.management.base import NoArgsCommand, CommandError
# import any models or stuff you need from your project
from your_app.models import Person, Place
# your custom command must reference the base management classes like this:
class Command(NoArgsCommand):
# it's useful to describe what the function does:
help = 'Deletes all people that aren't associated with places'
def handle_noargs(self, **options):
# now write your normal code here
What's important here is the class Command(NoArgsCommand) and then the subsequent def handle_noargs(self, **options):. Refer to the documentation, but these things 'define' the code you're writing as a management command. Don't worry too much about them to start, just put them in there and it will work!
Finally, inside the def handle() part, add your code. Now this can work like any normal view - create things, delete things, send emails, change things. There's no limit. Also, depending on what you're going to do, there's no need to have a return HttpResponse or similar at the end. However, I do like to have cron send me an email, or write in a log, just so I know what it's done in case errors occur.
Setting up the cron job
Now this becomes the most simple part - simply login to your server, and type crontab -e. If you have a cron file already, it will open it. If you don't, it will create one.
In the cron file, add something like this:
1 1 * * * python /path/to/project/manage.py name_of_your_command
eg.
1 1 * * * python /var/lib/django/project/manage.py delete_old_comments
The above command would run every day at 1.01am - check the cron documentation for how to set other time values.
Final advice
It's pretty simple, but if I have one piece of advice - test it thoroughly! Remember that hopefully, this cronjob will save you time and effort by running in the background, continually cleaning things up or doing regular tasks for you. But if you don't test it properly, then it might end up causing you more headaches in the future - imagine waking up in 2 months time to find that your lazy cronjob has deleted all the new comments instead of the old ones!!
