カスタム django-admin コマンドの実装Link to this heading
manage.py を用いることで独自のアクションを登録する事ができます。例として、あなたが配布している Django アプリケーションに manage.py アクションを追加したくなったとします。このドキュメントでは、このチュートリアル で作成した polls アプリケーションに独自の closepoll コマンドを追加します。
それを実現するには、maangement/commands ディレクトリをアプリケーションに追加するだけで済みます。Django はディレクトリ名がアンダースコアで始まらないディレクトリ内の Python モジュール毎に manage.py コマンドを追加します。
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py
Python 2 系においては、上に示すように management および management/commands ディレクトリそれぞれに __init__.py を追加しなければ実装したコマンドが検知されません。
この例では、closepoll コマンドは polls アプリケーションを INSTALLED_APPS に含むプロジェクト全てで利用できるようになります。
_private.py モジュールは管理コマンドとして利用できません。
closepoll.py モジュールには一つだけ満たすべき要件が有ります。 -- BaseCommand クラスもしくはその サブクラス の一つを継承した Command クラスを定義する必要が有ります。
コマンドを実装するには、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_id', nargs='+', type=int)
def handle(self, *args, **options):
for poll_id in options['poll_id']:
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))
新たに作成したカスタムコマンドは python manage.py closepoll <poll_id> と実行する事で利用できます。
handle() メソッドは一つ以上の poll_ids を受け取り、それぞれに対応した poll.opened を False にセットします。もしコマンドの利用者が存在しない poll を指定した場合、CommandError 例外が発生します。poll.opened 属性は元の チュートリアル には存在しないので、この例では polls.models.Question モデルに追加しました。
省略可能な引数を受け入れるLink to this heading
ここまで実装した closepoll に対し、別途コマンドラインオプションを受け取ることで指定された投票を閉じる代わりに削除するよう機能追加する事も容易に可能です。これらのオプション機能は add_arguments() メソッドによって以下のように追加できます。:
class Command(BaseCommand):
def add_arguments(self, parser):
# Positional arguments
parser.add_argument('poll_id', nargs='+', type=int)
# Named (optional) arguments
parser.add_argument(
'--delete',
action='store_true',
dest='delete',
default=False,
help='Delete poll instead of closing it',
)
def handle(self, *args, **options):
# ...
if options['delete']:
poll.delete()
# ...
オプション(例では delete)は handle メソッドで辞書型変数の引数として利用可能です。add_argument の利用についてより詳細な情報を得るには Python 公式ドキュメントの argparse を参照してください。
独自のコマンドラインオプションを追加できるのに加え、management commands に定義された --verbosity や --traceback といったオプションも標準で利用できます。
管理コマンドとロケールLink to this heading
標準では、BaseCommand.execute() メソッドは、Django に含まれる一部のコマンドが、プロジェクト全体を通じて中立な文字列の言語を必要とするタスク(例えばエンドユーザーに対するコンテンツ出力やデータベースへのデータ投入など)を実行するため、翻訳処理を無効化しています。
何らかの理由でカスタム管理コマンドから特定のロケールを利用する必要が有る場合は、I18N をサポートしているコードから提供される関数を利用している handle() メソッド内で手動で activate と deactivate を行う必要が有ります。
from django.core.management.base import BaseCommand, CommandError
from django.utils import translation
class Command(BaseCommand):
...
def handle(self, *args, **options):
# Activate a fixed locale, e.g. Russian
translation.activate('ru')
# Or you can activate the LANGUAGE_CODE # chosen in the settings:
from django.conf import settings
translation.activate(settings.LANGUAGE_CODE)
# Your command logic here
...
translation.deactivate()
単純に設定されたロケールをコマンドに利用させ、Django がそれを無効化しないようにしたい状況も考えられます。その状況では BaseCommand.leave_locale_alone オプションを利用する事で望む結果を得ることができます。
ただし先に述べた状況に取り組む場合、多様なロケールでのシステム管理コマンドの実行には細心の注意を払う必要が有る事を考慮しておくべきです。すなわち以下に示す点に注意してください:
そのコマンドが実行される際は設定値
USE_I18Nが常にTrueである事を確認してください。(これは Django を処理する動的ランタイム環境が翻訳機能を即座に無効化する事に起因する潜在的な問題の好例です)作成したコマンドとロケールが変わる事で振る舞いが変わるコードをレビューし、作成したコマンドにおいて予想される振る舞いへの影響を評価してください。
テストLink to this heading
カスタム管理コマンドのテストに関する情報は テストに関するページ で得ることができます。
Overriding commandsLink to this heading
Django registers the built-in commands and then searches for commands in
INSTALLED_APPS in reverse. During the search, if a command name
duplicates an already registered command, the newly discovered command
overrides the first.
In other words, to override a command, the new command must have the same name
and its app must be before the overridden command's app in
INSTALLED_APPS.
Management commands from third-party apps that have been unintentionally
overridden can be made available under a new name by creating a new command in
one of your project's apps (ordered before the third-party app in
INSTALLED_APPS) which imports the Command of the overridden
command.
Command オブジェクトLink to this heading
- class BaseCommandLink to this definition
全ての管理コマンドの派生元となる基底クラス。
コマンドライン引数を処理したり応答からコードの該当箇所を洗い出す機構など全てにアクセスしたい場合に利用してください。それらの振る舞いを代える必要が無ければ、:ref:`サブクラス<ref-basecommand-subclasses>`の利用を検討してください。
BaseCommand クラスのサブクラス化には handle() メソッドの実装が必要です。
属性Link to this heading
属性は全て派生クラスでセットでき、BaseCommand クラスの サブクラス で利用可能です。
- BaseCommand.helpLink to this definition
コマンドに関する短い説明、ユーザーが
python manage.py help <command>を実行する事でヘルプメッセージとして表示されます。
- BaseCommand.missing_args_messageLink to this definition
入力が必須の位置引数を定義しており、その引数が失われている場合に返すエラーメッセージを任意に設定する事ができます。デフォルトの出力は
argparseによる出力("too few arguments")です。
- BaseCommand.output_transactionLink to this definition
A boolean indicating whether the command outputs SQL statements; if
True, the output will automatically be wrapped withBEGIN;andCOMMIT;. Default value isFalse.
- BaseCommand.requires_migrations_checksLink to this definition
-
ブーリアン値。
Trueの場合、ディスク上に存在する一連のマイグレーション定義がデータベース上に保存されたマイグレーション定義とマッチしない場合に警告を出力します。この警告はコマンドの実行を停止させる物ではありません。デフォルトの値はFalseです。
- BaseCommand.requires_system_checksLink to this definition
ブーリアン値。
Trueの場合、コマンド実行前に Django プロジェクト全体が潜在的な問題を抱えていないかチェックされます。デフォルトの値はTrueです。
- BaseCommand.leave_locale_aloneLink to this definition
A boolean indicating whether the locale set in settings should be preserved during the execution of the command instead of translations being deactivated.
デフォルトの値は
Falseです。Make sure you know what you are doing if you decide to change the value of this option in your custom command if it creates database content that is locale-sensitive and such content shouldn't contain any translations (like it happens e.g. with
django.contrib.authpermissions) as activating any locale might cause unintended effects. See the Management commands and locales section above for further details.
- BaseCommand.styleLink to this definition
stdoutやstderrを記述した際にカラー出力を補助するインスタンス変数です。以下の利用例を参照ください:self.stdout.write(self.style.SUCCESS('...'))カラーパレットの調整と利用可能なスタイルについては Syntax coloring を参照してください(このセクションに記述されている "roles" のアルファベットを大文字にすると利用できます)。
--no-colorオプションを渡してコマンドを実行した場合、全てのself.style()呼び出しはオリジナルのカラー分けされていない出力を行います。
メソッドLink to this heading
BaseCommand has a few methods that can be overridden but only
the handle() method must be implemented.
- BaseCommand.add_arguments(parser)Link to this definition
コマンドに渡されたコマンドライン引数を操作するパーサーを追加するためのエントリポイントです。カスタム管理コマンドが受け取る位置引数およびオプション引数を追加するためにはこのメソッドをオーバーライドする必要が有ります。直接
BaseCommandを継承している場合はsuper()の呼び出しは必要有りません。
- BaseCommand.get_version()Link to this definition
Returns the Django version, which should be correct for all built-in Django commands. User-supplied commands can override this method to return their own version.
- BaseCommand.execute(*args, **options)Link to this definition
コマンドを実行し、必要とされた場合(
requires_system_checks属性によって設定可能)システムチェックを行います。コマンドがCommandError例外を発生させた場合は、実行を中断して stderr に出力します。
- BaseCommand.handle(*args, **options)Link to this definition
コマンドにおける実際の処理内容。サブクラスはこのメソッドを実装しなくてはならない。
stdoutに出力される Unicode 文字列(output_transactionがTrueの場合BEGIN;とCOMMIT;で囲まれている)を返す場合がある。
- BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)Link to this definition
潜在的な問題のために Django プロジェクト全体を検証するシステムチェックフレームワークを利用します。致命的な問題は
CommandError例外を発生し、警告は stderr への出力、重要でない通知は stdout への出力となります。app_configsおよびtagsが共にNoneであった場合、全てのシステムチェックが実行されます。tagsはチェックタグ、例えばcompatibilityあるいはmodels等、のリストとなります。
BaseCommand のサブクラスLink to this heading
- class AppCommandLink to this definition
一つ以上のインストールされたアプリケーションラベルを引数として受け取り、それぞれに対して何らかの処理を行う管理コマンド。
handle() を実装する代わりに、サブクラスでは、アプリケーション毎に一度ずつだけ呼び出される handle_app_config() を実装する必要が有ります。
- AppCommand.handle_app_config(app_config, **options)Link to this definition
コマンドラインで渡されたアプリケーションラベル個々に対応している
AppConfigのインスタンスであるapp_configに応じたコマンドの処理を行います。
- class LabelCommandLink to this definition
A management command which takes one or more arbitrary arguments (labels) on the command line, and does something with each of them.
Rather than implementing handle(), subclasses must implement
handle_label(), which will be called once for each label.
- LabelCommand.labelLink to this definition
コマンドに渡される任意引数について記述した文字列。この文字列はコマンドの使用法やエラーメッセージに利用します。デフォルトは
'label'です。
- LabelCommand.handle_label(label, **options)Link to this definition
コマンドラインに渡された文字列である
labelに対応したコマンドの処理を行います。
コマンドが発生させる例外Link to this heading
- exception CommandErrorLink to this definition
管理コマンド実行中に発生した問題について示した例外クラス。
コマンドラインコンソールから管理コマンドを実行中にこの例外が送出された場合、その例外は捕捉されて適切な出力ストリーム(例えば stderr 等)に整形されたエラーメッセージを表示させます。結果として、例外の送出は(エラーに関する明快な記述と併せて)コマンド実行中何らかの問題が発生した場合に状態を示す好ましい方法となります。
call_command() を介して管理コマンドが実行された場合は、例外の捕捉をするかどうかは実装に依存します。