カスタム django-admin
コマンドの作り方¶
manage.py
を用いることで独自のアクションを登録する事ができます。例として、あなたが配布している Django アプリケーションに manage.py
アクションを追加したくなったとします。このドキュメントでは、このチュートリアル で作成した polls
アプリケーションに独自の closepoll
コマンドを追加します。
独自のコマンドを追加するためには、 management/commands
ディレクトリをアプリケーションに追加してください。Djangoは、そのディレクトリ内のアンダーバーで始まらないPythonモジュールすべてを manage.py
コマンドに登録します。例えば:
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py
この例では、closepoll
コマンドは polls
アプリケーションを INSTALLED_APPS
に含むプロジェクト全てで利用できるようになります。
_private.py
モジュールは管理コマンドとして利用できません。
closepoll.py
モジュールには一つだけ満たすべき要件があります。それは、 BaseCommand
クラスもしくはその サブクラス の一つを継承した Command
クラスを定義することです。
スタンドアロンのスクリプト
カスタム管理コマンドはスタンドアロンのスクリプト、 UNIX の crontab や Windows のタスクスケジューラ管理パネルから定期的に実行されるスクリプトを処理する場合に特に有用です。
コマンドを実装するには、polls/management/commands/closepoll.py
を以下のように編集してください:
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
class Command(BaseCommand):
help = "Closes the specified poll for voting"
def add_arguments(self, parser):
parser.add_argument("poll_ids", nargs="+", type=int)
def handle(self, *args, **options):
for poll_id in options["poll_ids"]:
try:
poll = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise CommandError('Poll "%s" does not exist' % poll_id)
poll.opened = False
poll.save()
self.stdout.write(
self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)
)
注釈
管理コマンドを使用してコンソール出力を提供したい場合は、直接 stdout
と stderr
に出力するのではなく、self.stdout
と self.stderr
に書き込むべきです。これらのプロキシを使用することで、カスタムコマンドのテストがはるかに簡単になります。また、メッセージの終わりに改行文字を追加する必要はないことにも注意してください。ending
パラメータを指定しない限り、改行文字は自動的に追加されます:
self.stdout.write("Unterminated line", ending="")
新たに作成したカスタムコマンドは python manage.py closepoll <poll_ids>
と実行する事で利用できます。
handle()
メソッドは一つ以上の poll_ids
を受け取り、それぞれに対応した poll.opened
を False
にセットします。もしコマンドの利用者が存在しない poll を指定した場合、CommandError
例外が発生します。poll.opened
属性は元の チュートリアル には存在しないので、この例では polls.models.Question
モデルに追加しました。
省略可能な引数を受け入れる¶
上記の closepoll
は、追加のコマンドラインオプションを受け入れることで、投票を閉じる代わりに削除するように簡単に変更できます。これらのカスタムオプションは、次のように add_arguments()
メソッドで追加できます:
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument("poll_ids", nargs="+", type=int)
# Named (optional) arguments
parser.add_argument(
"--delete",
action="store_true",
help="Delete poll instead of closing it",
)
def handle(self, *args, **options):
# ...
if options["delete"]:
poll.delete()
# ...
オプション(例では delete
)は handle メソッドで辞書型変数の引数として利用可能です。add_argument
の利用についてより詳細な情報を得るには Python 公式ドキュメントの argparse
を参照してください。
独自のコマンドラインオプションを追加できるのに加え、管理コマンド に定義された --verbosity
や --traceback
といったオプションも標準で利用できます。
管理コマンドとロケール¶
デフォルトでは、管理コマンドは現在アクティブなロケールで実行されます。
何らかの理由でカスタム管理コマンドをアクティブなロケールなしで実行する必要がある (たとえば、翻訳されたコンテンツがデータベースに挿入されないようにしたい) 場合は、 handle()
メソッドで @no_translations
デコレータを使用して翻訳を無効にします。
from django.core.management.base import BaseCommand, no_translations
class Command(BaseCommand):
...
@no_translations
def handle(self, *args, **options): ...
翻訳の非アクティブ化には構成設定へのアクセスが必要なので、構成設定なしで機能するコマンドにデコレータを使用することはできません。
テスト¶
カスタム管理コマンドのテストに関する情報は テストに関するページ で得ることができます。
コマンドのオーバーライド¶
Djangoは、ビルトインコマンドを読み込んだ後に INSTALLED_APPS
を逆順に検索してコマンドを登録します。この検索の際に、すでに登録済みのコマンド名と重複したコマンド名が見つかった場合、新しく見つかったコマンドで最初に見つけたコマンドをオーバーライドします。
別の言い方をすると、コマンドをオーバーライドするためには、新しいコマンドは、オーバーライドするコマンドと同じ名前でなければなりません。そして、そのアプリは、INSTALLED_APPS
で、オーバーライドするコマンドのアプリよりも前にある必要があります。
意図せずオーバーライドされたサードパーティアプリからの管理コマンドは、オーバーライドされたコマンドの Command
をインポートするプロジェクトのアプリ(INSTALLED_APPS
でサードパーティアプリの前に注文) の1つで新しいコマンドを作成することにより、新しい名前で使用可能にできます。
Command オブジェクト¶
全ての管理コマンドの派生元となる基底クラス。
コマンドライン引数を解析し、それに対してどのコードを呼び出すかを決定するすべてのメカニズムにアクセスしたい場合は、このクラスを使用してください。そのような動作を変更する必要がない場合は、 サブクラス のいずれかを使用することを検討してください。
BaseCommand
クラスのサブクラス化には handle()
メソッドの実装が必要です。
属性¶
全ての属性は派生クラスでセットでき、BaseCommand
クラスの サブクラス で利用可能です。
- BaseCommand.help¶
コマンドに関する短い説明。ユーザーが
python manage.py help <command>
を実行することでヘルプメッセージとして表示されます。
- BaseCommand.missing_args_message¶
コマンドが必須の位置引数を定義している場合、引数が足りない場合に返されるエラーメッセージをカスタマイズできます。デフォルトは
argparse
によって出力されます ("too few arguments")。
- BaseCommand.output_transaction¶
コマンドが SQL 文を出力するかどうかを決めるブール値。
True
の場合、出力文が自動的にBEGIN;
とCOMMIT;
で囲まれます。デフォルトの値はFalse
です。
- BaseCommand.requires_migrations_checks¶
Boolean。
True
の場合、ディスク上に存在する一連のマイグレーション定義がデータベース上に保存されたマイグレーション定義とマッチしない場合に警告を出力します。この警告はコマンドの実行を停止させる物ではありません。デフォルトの値はFalse
です。
- BaseCommand.requires_system_checks¶
例えば
[Tags.staticfiles, Tags.models]
のようなタグのリストやタプル。 指定したタグに登録された システムチェックは、コマンドを実行する前にエラーがないかチェックされます。'__all__'
を使用することで、すべてのシステムチェックを実行するように指定することができます。デフォルトでは'__all__'
に設定されています。
- BaseCommand.style¶
stdout
やstderr
を記述した際にカラー出力を補助するインスタンス変数です。以下の利用例を参照ください:self.stdout.write(self.style.SUCCESS("..."))
カラーパレットの調整と利用可能なスタイルについては シンタックスカラーリング を参照してください (このセクションに記述されている "roles" のアルファベットを大文字にすると利用できます)。
--no-color
オプションを渡してコマンドを実行した場合、全てのself.style()
呼び出しはオリジナルのカラー分けされていない出力を行います。
- BaseCommand.suppressed_base_arguments¶
ヘルプ出力で抑制するデフォルトのコマンドオプション。これは、オプション名のセットでなければなりません(例:'--verbosity')。抑制されたオプションのデフォルト値はそのまま渡されます。
メソッド¶
BaseCommand
には、いくつかのオーバーライド可能なメソッドが含まれています。しかし、handle()
メソッドだけは、実装する必要があります。
サブクラス内でのコンストラクタの実装
BaseCommand
を継承したサブクラス内で __init__
を実装する場合、BaseCommand
の __init__
を呼び出す必要があります:
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# ...
- BaseCommand.create_parser(prog_name, subcommand, **kwargs)[ソース]¶
CommandParser
インスタンスを返します。これはArgumentParser
サブクラスで、Django用にいくつかカスタマイズされています。このメソッドをオーバーライドし、
ArgumentParser
パラメータのkwargs
を使ってsuper()
を呼び出すことでインスタンスをカスタマイズできます。
- BaseCommand.add_arguments(parser)[ソース]¶
コマンドに渡されたコマンドライン引数を操作するパーサーを追加するためのエントリポイントです。カスタム管理コマンドが受け取る位置引数およびオプション引数を追加するためにはこのメソッドをオーバーライドする必要があります。直接
BaseCommand
を継承している場合はsuper()
の呼び出しは必要ありません。
- BaseCommand.get_version()[ソース]¶
Djangoのバージョンを返します。これはすべての組み込みDjangoコマンドに対して正しいはずです。 ユーザー指定のコマンドは、このメソッドをオーバーライドして独自のバージョンを返すことができます。
- BaseCommand.execute(*args, **options)[ソース]¶
コマンドを実行し、必要とされた場合(
requires_system_checks
属性によって設定可能)システムチェックを行います。コマンドがCommandError
例外を発生させた場合は、実行を中断してstderr
に出力します。
コード中での管理コマンドの呼び出し
カスタム管理コマンドを実行するためにコード中から execute()
を直接呼び出す事は避けてください。代わりに call_command()
を利用してください。
- BaseCommand.handle(*args, **options)[ソース]¶
コマンドにおける実際の処理内容。サブクラスはこのメソッドを実装しなければなりません。
stdout
に出力される文字列を返すことができます (output_transaction
がTrue
の場合、文字列はBEGIN;
とCOMMIT;
で挟まれて出力されます)。
- BaseCommand.check(app_configs=None, tags=None, display_num_errors=False, include_deployment_checks=False, fail_level=checks.ERROR, databases=None)[ソース]¶
潜在的な問題のために Django プロジェクト全体を検証するシステムチェックフレームワークを利用します。致命的な問題は
CommandError
例外を発生し、警告はstderr
への出力、重要でない通知はstdout
への出力となります。app_configs
およびtags
が共にNone
であった場合、デプロイメントとデータベース関連のチェック以外の全てのシステムチェックが実行されます。tags
はチェックタグ、例えばcompatibility
あるいはmodels
等、のリストとなります。また、
include_deployment_checks=True
を渡すとデプロイメントのチェックを行い、databases
にデータベースエイリアスのリストを渡すとデータベース関連のチェックを行います。
BaseCommand
のサブクラス¶
- class AppCommand¶
一つ以上のインストールされたアプリケーションラベルを引数として受け取り、それぞれに対して何らかの処理を行う管理コマンド。
handle()
を実装する代わりに、サブクラスでは、アプリケーション毎に一度ずつだけ呼び出される handle_app_config()
を実装する必要があります。
- AppCommand.handle_app_config(app_config, **options)¶
コマンドラインで渡されたアプリケーションラベル個々に対応している
AppConfig
のインスタンスであるapp_config
に応じたコマンドの処理を行います。
- class LabelCommand¶
コマンドラインで1つ以上の任意の引数(ラベル)を受け取り、それぞれに対して何かを行う管理コマンド。
サブクラスは、handle()
を実装するのではなく、ラベルごとに1回呼び出される handle_label()
を実装する必要があります。
- LabelCommand.label¶
コマンドに渡される任意引数について記述した文字列。この文字列はコマンドの使用法やエラーメッセージに利用します。デフォルトは
'label'
です。
- LabelCommand.handle_label(label, **options)¶
コマンドラインに渡された文字列である
label
に対応したコマンドの処理を行います。
コマンドが発生させる例外¶
管理コマンド実行中に発生した問題について示した例外クラス。
この例外がコマンドラインコンソールからの管理コマンドの実行中に発生した場合、キャッチされて適切な出力ストリーム(つまり、stderr
)に対して整形されたエラーメッセージに変換されます。そのため、コマンドの実行中に何かが間違っていることを示す場合は、この例外を(エラーの理にかなった説明とともに)発生させることを推奨します。任意で returncode
引数を受け入れて、sys.exit()
で管理コマンドが終了する際の終了ステータスをカスタマイズできます。
call_command()
を介して管理コマンドが実行された場合は、例外の捕捉をするかどうかは実装に依存します。