[Django] カスタムコマンドを作成する

Djangoには独自の管理コマンドを定義する機能が用意されています。

独自コマンド

ここで言うDjangoのコマンドとは、

python manage.py runserver

などmanage.pyの後ろに続けるコマンドのことです。

定義する

早速、独自のコマンドを作っていきます。

今回は、コンソールにHello World!するだけのコマンドhelloを実装していきます。

ファイルを作成する

事前準備

独自コマンドを記述するファイルは、配置する場所が決まっているのでまずはそのためのディレクトリを作成します。

Djangoのプロジェクトの名前をproject、アプリケーションの名前をsampleとします。

project
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── sample
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

こんな感じのディレクトリ構成になっていることを想定します。

アプリケーションディレクトリsampleの中にmanagement、そのなかにcommandsというディレクトリを作ります。 さらにそれぞれの中に__init__.pyという名前のファイルを配置します。

project
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── sample
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── management # 追加
    │   ├── __init__.py # 追加
    │   └── commands # 追加
    │       └── __init__.py # 追加
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

配置後のディレクトリの構成はこんな感じです。

コマンドを記述するファイルを作る

この時、ファイル名がそのままコマンド名になります。

今回はファイル名をhello.pyとします。

このファイル名はご自身のお好きな名前で作ってもらって構いません。

先ほど作ったcommandsディレクトリの中にhello.pyを作ります。

project
├── manage.py
├── project
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── sample
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── management
    │   ├── __init__.py
    │   └── commands
    │       ├── hello.py # 追加
    │       └── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

コマンドを実装する

先程作成したファイルにプログラム本体を記述していきます。

DjangoのコマンドはBaseCommandクラスをを継承することで作成できます。

このとき継承したクラスの名前はCommandにする必要があります。

from django.core.management import BaseCommand

class Command(BaseCommand):

    def handle(self, *args, **options):
        self.stdout.write('Hello World!')

handleメソッドが本体でコマンドを叩かれた時にこのメソッドが実行されます。

今 作ったコマンドは、

python manage.py hello

とすれば実行出来ます。

オプションを追加する

流石にHello World!するだけだとつまらないので、色を付けたり、複数回hello出来るオプションをつけてみたいと思います。

add_argumentsメソッドでオプション引数を追加します。

コマンドライン引数の解析には内部でPythonの標準モジュールargparseが利用されます。

from django.core.management import BaseCommand

class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument('-n', default=1, type=int,
                            help='how many print. default is 1')
        parser.add_argument('--color',
                            type=str, default='')

    def handle(self, *args, **options):
        for _ in range(options['n']):
            text = 'Hello World!'
            color = options['color']
            if color == 'red':
                text = self.style.ERROR(text)
            elif color == 'yellow':
                text = self.style.WARNING(text)
            elif color == 'green':
                text = self.style.SUCCESS(text)
            self.stdout.write(text)

おまけ

普通に画面に文字を表示する分には、printself.stdout.writeもそう差はありませんが、 stdoutの代わりにstderrを利用する事で標準エラー出力に文字を送ることが出来るので見た目を統一するためにself.stdout.writeを利用することを推奨します。

最後に

ごく簡単にDjangoに独自のコマンドを追加する方法をご紹介しました。
普段よく使うアクションはコマンドにしておくと、何度も同じ作業をしなくて良くなるので積極的に利用していきたいですね。

参考

https://qiita.com/checkpoint/items/b6947501774b4008e077