I have used a few web frameworks over the years but I think I have finally found the one that suits my particular needs. I have played with RoR, Turbo Gears, Catalyst and a couple of others but none have actually made me want to write code instead of hoping that it allows me to write less. That was until I discovered Django. A friend of mine had said he was using for his website it but for some reason I managed to get it stuck in my head that he was using Mambo CMS so I never really paid it much attention.

Something that I usually need in a web application is some way to interact with it from the command line, I am a systems administrator -CLI is what I do. In the past I have just connected directly to the database from my scripts but it has always bothered my that I have already done all this business logic in my models and I end up having to repeat it in a limited fashion. I have had a brief look around a couple of times but never found anything that works to my satisfaction until I found the following code on this site by James Bennett http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/. James has several methods on that page but I think that this one will be best if you plan on distributing your application.

import os
from optparse import OptionParser

usage = "usage: %prog -s SETTINGS | --settings=SETTINGS"
parser = OptionParser(usage)
parser.add_option('-s', '--settings', dest='settings', metavar='SETTINGS',
                          help="The Django settings module to use")
(options, args) = parser.parse_args()
if not options.settings:
    parser.error("You must specify a settings module")

    os.environ['DJANGO_SETTINGS_MODULE'] = options.settings

LOG_FILENAME = 'logging.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.INFO,)

The issue with this was after a while I realised that it didn’t work unless you were in the base directory of your application, this may be because I was in doing something wrong - I am relatively new to python. Then I thought how does Django do it ? The answer to this lived in the core.management.__init__ method setup_environ(). Anyway I ended up using a mashup of the two concepts to arrive at the following code. It is a bit long winded but it works from any directory so the script can be anywhere. It sets the environment up based on the settings file being in the normal place - in the base directory of the application.

import os
import sys
from optparse import OptionParser

# Parse the command line options
usage = "usage: %prog -s SETTINGS | --settings=SETTINGS"
parser = OptionParser(usage)
parser.add_option('-s', '--settings', dest='settings', metavar='SETTINGS',
                          help="The Django settings module to use")
(options, args) = parser.parse_args()
if not options.settings:
    parser.error("You must specify a settings module")

# set
project_directory, settings_filename = os.path.split(options.settings)
if project_directory == os.curdir or not project_directory:
    project_directory = os.getcwd()
project_name = os.path.basename(project_directory)
settings_name = os.path.splitext(settings_filename)[0]
sys.path.append(os.path.join(project_directory, os.pardir))
project_module = __import__(project_name, {}, {}, [''])
sys.path.pop()

os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)

With that added at the top of my scripts I can keep may maintenance scripts in a place more logical like /usr/local/bin instead of the project root and run them like this

/usr/local/bin/myscript.py --settings=/path/to/project/settings.py