Djangoを使ったアプリケーションのバッチ処理

Webアプリを作っていると集計などの目的のため、定期的にバックグランドでバッチ処理を走らせるというケースはよくあります。その際、DB接続などの設定をWebアプリの設定を流用できると、開発も管理も楽になります。Djangoではdjango-adminのコマンドを自作することで、コマンドラインからキックしたプログラムにてWebアプリ用の設定を使えるようになります。(参考ドキュメント: Writing custom django-admin commands)このコマンドをcrontabに登録すれば、定期的にバックグランドでバッチ処理を走らせることができます。

目次

  1. 準備
  2. 基本的な作り方
  3. カスタムオプションを利用

準備

django-adminのコマンドを自作するためには、まずはアプリ(startappコマンドで作成したもの)の下に「management」というディレクトリを作成します。次に、そのディレクトリの中に「commands」ディレクトリを作成します。そして、「commands」ディレクトリ下に自作するdjango-adminのモジュールを作成していきます。なお、「management」と「commands」ディレクトリ下には「init.py」ファイルが必要になります。

cd [startappで作成したアプリ]
mkdir management
cd management
touch __init__.py
mkdir commands
cd commands
touch __init__.py
touch [自作するdjango-adminコマンドのモジュール]

また、「settings.py」の「INSTALLED_APPS」にアプリを追加しておかないと、自作のdjango-adminコマンドのキックに失敗するのでご注意ください。

↑ 目次に戻る

基本的な作り方

自作のdjango-adminの作り方の説明です。まず最初に、「django.core.management.base.BaseCommand」クラスを継承した「Command」クラスを作成します。そのクラスに「handle」というメソッドを定義し、その中に自作したdjango-adminのコマンドが実施する処理を書いていきます。

# coding: utf-8

import logging
from django.core.management.base import BaseCommand, CommandError


class Command(BaseCommand):
    args = '<target_id target_id ...>'
    help = u'カスタムAdminコマンドのテストです'

    def handle(self, *args, **options):
        for target_id in args:
            logging.info('target_id: %s' % target_id)

上記は、受け取った引数をログに出力する簡単なコマンドです。これを実施すると以下のような結果になります。

$ python manage.py custom_command1 1 2 3
[INFO] (custom_command1.py:13) target_id: 1
[INFO] (custom_command1.py:13) target_id: 2
[INFO] (custom_command1.py:13) target_id: 3

ここでは、起動時に指定した引数「1」、「2」、「3」が「args」変数に入っていて、それをログに出力しています。なお、「Command」クラス直下に定義している「args」と「help」変数は、ヘルプメッセージを出力した場合に使われます。

$ python manage.py custom_command1 --help
Usage: manage.py custom_command1 [options] <target_id target_id ...>

カスタムAdminコマンドのテストです

Options:
  -v VERBOSITY, --verbosity=VERBOSITY
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=all output
  --settings=SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath=PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Print traceback on exception
  --version             show program's version number and exit
  -h, --help            show this help message and exit

↑ 目次に戻る

カスタムオプションを利用

実装する処理によっては、複数の引数を取得したいケースがあります。そういった場合、「make_option」関数を使って引数を追加していくことができます。このサンプルでは、「mode」と「ignore」という引数を追加しています。

# coding: utf-8

import logging
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError

DEFAULT_MODE = 0


class Command(BaseCommand):
    args = '<target_id target_id ...>'
    help = u'カスタムAdminコマンドのテストです'
    option_list = BaseCommand.option_list + (
        make_option('-m', '--mode', action='store',
                    type='int', dest='mode', default=DEFAULT_MODE,
                    help=u'0(default): 通常モード, 1: 復旧モード'),
        make_option('-i', '--ignore', action='store_true',
                    dest='ignore', default=False,
                    help=u'false(default): 例外発生で停止, true: 例外を無視'),
    )

    def handle(self, *args, **options):
        for target_id in args:
            logging.info('target_id: %s' % target_id)
        mode = options['mode']
        ignore = options['ignore']
        logging.info('mode[type]: %s[%s]' % (mode, mode.__class__,))
        logging.info('ignore[type]: %s[%s]' % (ignore, ignore.__class__,))

make_optionの「-m」と「--mode」は引数を指定する際に使う文字です。例えば「-m 0」とか「--mode=1」といった形で引数を与えることができます。actionは与えた引数をどうするかを表します。「store」は引数を格納し、「store_true」は指定されていれば「True」といった感じです。destは指定された引数を取得する際のキーです。コードのように「options['キー']」でオプションの値を取得できます。詳しくはドキュメント「optparse — Parser for command line options」をご確認ください。

上記コマンドを実行すると以下のように出力結果になります。

$ python manage.py custom_command2 1 2 3 -m 0
[INFO] (custom_command2.py:24) target_id: 1
[INFO] (custom_command2.py:24) target_id: 2
[INFO] (custom_command2.py:24) target_id: 3
[INFO] (custom_command2.py:27) mode[type]: 0[<type 'int'>]
[INFO] (custom_command2.py:28) ignore[type]: False[<type 'bool'>]

$ python manage.py custom_command2 --mode=1 --ignore
[INFO] (custom_command2.py:27) mode[type]: 1[<type 'int'>]
[INFO] (custom_command2.py:28) ignore[type]: True[<type 'bool'>]

ヘルプメッセージにも反映されています。

$ python manage.py custom_command2 --help
Usage: manage.py custom_command2 [options] <target_id target_id ...>

カスタムAdminコマンドのテストです

Options:
  -v VERBOSITY, --verbosity=VERBOSITY
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=all output
  --settings=SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath=PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Print traceback on exception
  -m MODE, --mode=MODE  0(default): 通常モード, 1: 復旧モード
  -i, --ignore          false(default): 例外発生で停止, 1: 例外を無視
  --version             show program's version number and exit
  -h, --help            show this help message and exit

↑ 目次に戻る

この記事が役に立った場合、シェアしていただけると励みになります!!