DjangoでWebアプリ開発中に以下のようなことを思ったことありませんか?
このような場合、Djangoでコマンド実行すれば解決できるかもしれません。
本記事では、Djangoでコマンドを実行する方法をまとめましたので、よろしければ参考にしてください。
目次
手順概要
なお、以下の手順は以下の環境で動作確認済みです。
・Python 3.11.1
・Django==4.1.4
事前準備
事前準備としてコマンド実行用のファイルを作成します。
コマンド実行
(Pjojectを作っていなかったら以下を実行)
$ django-admin startproject mysite .
(事前準備)
$ cd mysite
$ python manage.py startapp myapp
$ mkdir -p myapp/management/commands
$ touch myapp/management/commands/__init__.py
$ touch myapp/management/commands/testcommand.py
settings.py(追記)
INSTALLED_APPS = [
...
'myapp.apps.MyappConfig'
]
フォルダ構成は以下の通り。
.
|-- myapp
| |-- 省略
| |-- management
| | `-- commands
| | |-- __init__.py
| | `-- testcommand.py
|-- manage.py
|-- mysite
`-- static
`-- 省略
コマンドファイルを書いていく
コマンドファイル(testcommand.py
)にはdjango.core.management.base.BaseCommand
を継承したCommand
クラスを作り、必要なメソッドをオーバーライドします。
/myapp/management/commands/testcommand.py
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "テストコマンド"
def handle(self, *args, **options):
if options['greeting']:
print("Hello!")
def add_arguments(self, parser):
parser.add_argument('--greeting', action='store_true', help='挨拶する')
ポイントは、
- BaseCommandを継承したCommandを定義すること
- Commandクラスの変数helpは
python manage.py help カスタムコマンド名
としたときに表示される説明文的なもの - handleメソッドを継承すること
- handleメソッド内に実行した処理を書く
コマンドを実行する
最後にコマンドを実行してみます。
コマンド実行
$ python manage.py testcommand --greeting
Hello!
$ python manage.py help testcommand
usage: manage.py testcommand [-h] [--greeting] [--version] [-v {0,1,2,3}]
[--settings SETTINGS] [--pythonpath PYTHONPATH]
[--traceback] [--no-color] [--force-color]
[--skip-checks]
テストコマンド
options:
-h, --help show this help message and exit
--greeting 挨拶する
...割愛
コマンドに引数を設定するには?
上の例では、コマンドの引数を想定していませんでしたが、引数も簡単に追加できます。
コマンドに引数を設定するには、parser.add_argument()
の引数をいくつか設定すればよいです。
引数 | 説明 |
---|---|
第一引数 | コマンドのオプション名 (例: '--greeting' ) |
nargs | 引数の数を設定できる(int , '?' , '*' , '+' などが使える) |
default | 第一引数で定義されたオプションが指定されたなかったときに この値を使って実行をする。 |
type | 引数の型を指定できる(int , str など) |
action | 引数の処理方法を指定できる ( 'store_true' を指定すると、第一引数のオプションが呼ばれたらTrue を返すようにできる。) |
help | ヘルプメッセージに説明を追加できる。 |
詳細は、こちらのページに記載あります。
例:引数に1つの文字列を設定する
/myapp/management/commands/testcommand.py
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "テストコマンド"
def handle(self, *args, **options):
if options['name']:
self.__name(options['name'])
def add_arguments(self, parser):
parser.add_argument('--name', nargs='?', default='shiguregaki', type=str, help='名前入りで挨拶する')
def __name(self, args):
print("Hello "+args)
コマンド実行結果
$ python manage.py testcommand --name shigure
Hello shigure
$ python manage.py testcommand
Hello shiguregaki
$ python manage.py testcommand --greeting
Hello!
Hello shiguregaki
$ python manage.py testcommand --name 0
Hello 0
【エラーケース】
$ python manage.py testcommand --name shigure 0
manage.py testcommand: error: unrecognized arguments: 0
・--name
オプションを指定しないと、default
引数で指定したshiguiregaki
で実行されています。
・が、--greeting
オプションのみでも--name
オプションの処理が実行されています。default
引数を指定することで意図しない動きにならないように注意が必要ですね。
・--name 0
と数値を指定してみましたが、文字列として読み取るようです。
例:引数に2つの数値を設定する
/myapp/management/commands/testcommand.py
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "テストコマンド"
def handle(self, *args, **options):
if options['greeting']:
print("Hello!")
if options['age']:
self.__age(options['age'])
def add_arguments(self, parser):
parser.add_argument('--greeting', action='store_true', help='挨拶する')
parser.add_argument('-a', '--age', nargs=2, type=int, help='年齢と誕生月入りで挨拶する')
def __age(self, args):
age = args[0]
birth_month = args[1]
print("Hello! I'm {0} years old. My Birthday month is {1}!".format(age, birth_month))
コマンド実行結果
$ python manage.py testcommand --age 20 4
Hello! I'm 20 years old. My Birthday month is 4!
$ python manage.py testcommand -a 25 5
Hello! I'm 25 years old. My Birthday month is 5!
$ python manage.py testcommand
(何も表示なし)
$ python manage.py testcommand --greeting
Hello!
【エラーケース】
$ python manage.py testcommand --age 20
manage.py testcommand: error: argument -a/--age: expected 2 arguments
$ python manage.py testcommand --age a b
manage.py testcommand: error: argument -a/--age: invalid int value: 'a'
・--age
と-a
の両方でオプションの実行ができています。
・今回は、default
の指定をしていないため、オプションを指定しなかった場合は__age()
が実行されていません。
以上!
コメント