# Django 6.0.7 ドキュメント

# カスタム `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()
            # ...

The option (`delete` in our example) is available in the options dict parameter of the handle method. See the `argparse` Python documentation for more about `add_argument` usage.

独自のコマンドラインオプションを追加できるのに加え、管理コマンド に定義された `--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 オブジェクト

class BaseCommand

全ての管理コマンドの派生元となる基底クラス。

コマンドライン引数を解析し、それに対してどのコードを呼び出すかを決定するすべてのメカニズムにアクセスしたい場合は、このクラスを使用してください。そのような動作を変更する必要がない場合は、 サブクラス のいずれかを使用することを検討してください。

`BaseCommand` クラスのサブクラス化には `handle()` メソッドの実装が必要です。

### 属性

全ての属性は派生クラスでセットでき、`BaseCommand` クラスの サブクラス で利用可能です。

BaseCommand.help

  コマンドに関する短い説明。ユーザーが `python manage.py help <command>` を実行することでヘルプメッセージとして表示されます。

BaseCommand.missing_args_message

  If your command defines mandatory positional arguments, you can customize the message error returned in the case of missing arguments. The default is output by `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.get_check_kwargs(options)

  `requires_system_checks` の値を `tag` 引数に変換するなど、 `check()` の呼び出しに引数を提供します。

  このメソッドをオーバーライドすると、 `check()` に渡される値が変更されます。例えば、データベース関連のチェックを有効にするには、 `get_check_kwargs()` をオーバーライドします:

      def get_check_kwargs(self, options):
          kwargs = super().get_check_kwargs(options)
          return {**kwargs, "databases": [options["database"]]}

### `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` に対応したコマンドの処理を行います。

### コマンドが発生させる例外

exception CommandError(returncode=1)

管理コマンド実行中に発生した問題について示した例外クラス。

この例外がコマンドラインコンソールからの管理コマンドの実行中に発生した場合、キャッチされて適切な出力ストリーム（つまり、`stderr`）に対して整形されたエラーメッセージに変換されます。そのため、コマンドの実行中に何かが間違っていることを示す場合は、この例外を（エラーの理にかなった説明とともに）発生させることを推奨します。任意で `returncode` 引数を受け入れて、`sys.exit()` で管理コマンドが終了する際の終了ステータスをカスタマイズできます。

`call_command()` を介して管理コマンドが実行された場合は、例外の捕捉をするかどうかは実装に依存します。