<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>David Fischer dot Name &#187; crontab</title>
	<atom:link href="http://www.davidfischer.name/tag/crontab/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.davidfischer.name</link>
	<description>Some Things to Some People</description>
	<lastBuildDate>Thu, 02 Sep 2010 05:58:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Django Scripting and the Crontab</title>
		<link>http://www.davidfischer.name/2010/02/django-scripting-and-the-crontab-2/</link>
		<comments>http://www.davidfischer.name/2010/02/django-scripting-and-the-crontab-2/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 00:13:20 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[crontab]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[documentation]]></category>

		<guid isPermaLink="false">http://www.davidfischer.name/?p=400</guid>
		<description><![CDATA[Sometimes, you need part of]]></description>
			<content:encoded><![CDATA[<p>Sometimes, you need part of your Django application to run from the command line. These scripts can be caching jobs that run periodically to speed up performance or data collection jobs that pull information from various sources into your application. Although James Bennett has a great article on writing <a href="http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/">standalone Django scripts</a>, I just wanted to update it with changes that have happened since 2007. I ran into this problem about the same time on both a work project and on a personal project.</p>
<h5>The problem with standalone scripts</h5>
<p>The basic problem is that you want your script to run in the context of your application. You want to access your databases in the normal way and you want to import modules by the same paths. In general, you can do all of this work yourself by making sure your <span style="font-family:monospace">PYTHONPATH</span> is correct and <span style="font-family:monospace">DJANGO_SETTINGS_MODULE</span> is set properly, but it is so much easier to just create a <a href="http://docs.djangoproject.com/en/dev/howto/custom-management-commands/">custom management command</a>. This is especially convenient since it makes your script portable (Windows, Mac &#038; Linux &#8212; crontab &#038; schedule tasks) as well easily distributable with your application.</p>
<h5>Custom management commands</h5>
<p>A custom management command is a command that can be run from <span style="font-family:monospace">manage.py</span>. Essentially, Django requires that you create the following type of structure under your application:</p>
<pre>management/
    __init__.py
    commands/
        __init__.py
        mycommand.py</pre>
<p>Then, in <span style="font-family:monospace">mycommand.py</span> you must subclass <span style="font-family:monospace">django.core.management.base.BaseCommand</span> like so:</p>
<pre><code class='python'>from optparse import make_option
from django.core.management.base import BaseCommand, CommandError

# Class MUST be named 'Command'
class Command(BaseCommand):

    # Displayed from 'manage.py help mycommand'
    help = "Your help message"

    # make_option requires options in optparse format
    option_list = BaseCommand.option_list  + (
                        make_option('--myoption', action='store',
                            dest='myoption',
                            default='default',
                            help='Option help message'),
                  )

    def handle(self, *app_labels, **options):
        """
        app_labels - app labels (eg. myapp in "manage.py reset myapp")
        options - configurable command line options
        """

        # Return a success message to display to the user on success
        # or raise a CommandError as a failure condition
        if options['myoption'] == 'default':
            return 'Success!'

        raise CommandError('Only the default is supported')
</code></pre>
<p>This will allow you to run (mycommand is named for mycommand.py):</p>
<pre>
> python manage.py mycommand
</pre>
<p>or create a crontab entry as follows:</p>
<pre>
* * * * * cd /home/path/to/project &#038;&#038; python manage.py mycommand
</pre>
<h5>Conclusion</h5>
<p>This provides the cleanest, most flexible way to build and support standalone scripts that can be used outside of the web server. It will run in exactly the same environment as your application and the same modules used in your application can be used here. The only problem I ran into was that custom management commands <strong>must</strong> be run from the same directory as <span style="font-family:monospace">manage.py</span>.</p>
<p><strong>Edit</strong>: I added thorough documentation on management commands to ticket <a href="http://code.djangoproject.com/ticket/9170">#9170</a></p>
<p><strong>Update</strong>: The 1.2 documentation contains the <a href="http://docs.djangoproject.com/en/1.2/howto/custom-management-commands/">changes</a> from my patch.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.davidfischer.name/2010/02/django-scripting-and-the-crontab-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
