Djangoのアクションを追加してmanage.pyから実行する

現在仕事でDjangoを使ってWebアプリを書いていて、バッチ処理を今まで以下のように書いていたのですが、アクションを自作するのも簡単で便利だったのでメモ。

今まで使っていたバッチ処理のスクリプト
#!/usr/bin/env python
# coding: utf-8

import os
import sys

DJANGO_HOME = '/usr/local/django'
PROJECT = 'mysite'
PROJECT_HOME = os.path.join(DJANGO_HOME, PROJECT)
SETTINGS_MODULE = '.'.join([PROJECT, 'settings'])

sys.path.append(PROJECT_HOME)
os.environ['DJANGO_SETTINGS_MODULE'] = SETTINGS_MODULE

def main():
    処理

if __name__ == '__main__':
    main()
アクションの追加

仕組みはdjango/core/management/__init__.pyを見ればわかりますが、簡単にまとめるとdjango/core配下又はsettings.INSTALLED_APPSのタプルに指定したアプリケーション配下のmanagement/commandsディレクトリからコマンドが検索されて実行されます。(management/__init__.pyとmanagement/commands/__init__.pyが必要です)

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   app/management/__init__.py
#	new file:   app/management/commands/__init__.py
#	new file:   app/management/commands/spam.py

コマンドは1コマンド1ファイルでコマンド名とファイル名をマッチさせます。
また、コマンドファイルはCommandという名前のクラスにhandleというメソッドを実装しておく必要があります。
以下コマンドのサンプルです。

# coding: utf-8
"""
ファイル名: project/app/management/commands/spam.py
"""

# CommandクラスはBaseCommand又はBaseCommandを継承しているクラスを継承する必要があります
# CommandErrorは例外クラスです
from django.core.management.base import BaseCommand, CommandError

from app.models import SomeModel

class Command(BaseCommand):
    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        # ...

    # このメソッドが実行されます
    def handle(self, *args, **kwargs):
        for k in args:
            try:
                obj = SomeModel.objects.get(some_field__contains=k)
            except SomeException:
                raise CommandError('some error')
            obj.field = 'some value'
            obj.save()

アクションを自作する — Django v1.0 documentation
Writing custom django-admin commands | Django documentation | Django