# Django 4.1.8.dev20230308103347 ドキュメント

# How to create custom `django-admin` commands

`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` を参照してください。

独自のコマンドラインオプションを追加できるのに加え、management commands に定義された `--verbosity` や `--traceback` といったオプションも標準で利用できます。

## 管理コマンドとロケール

デフォルトでは、管理コマンドは現在アクティブなロケールで実行されます。

何らかの理由でカスタム django-admin コマンドをアクティブなロケールなしで実行する必要がある場合 (たとえば、翻訳されたコンテンツがデータベースに挿入されないようにする)、`handle()` method:: メソッドで@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`

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

コマンドライン引数を処理したり応答からコードの該当箇所を洗い出す機構など全てにアクセスしたい場合に利用してください。それらの振る舞いを代える必要が無ければ、:ref:`サブクラス<ref-basecommand-subclasses>`の利用を検討してください。

`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`

  A list or tuple of tags, e.g. `[Tags.staticfiles, Tags.models]`. System checks registered in the chosen tags will be checked for errors prior to executing the command. The value `'__all__'` can be used to specify that all system checks should be performed. Default value is `'__all__'`.

`BaseCommand.``style`

  `stdout` や `stderr` を記述した際にカラー出力を補助するインスタンス変数です。以下の利用例を参照ください:

      self.stdout.write(self.style.SUCCESS('...'))

  カラーパレットの調整と利用可能なスタイルについては Syntax coloring を参照してください (このセクションに記述されている "roles" のアルファベットを大文字にすると利用できます)。

  `--no-color` オプションを渡してコマンドを実行した場合、全ての `self.style()` 呼び出しはオリジナルのカラー分けされていない出力を行います。

`BaseCommand.``suppressed_base_arguments`
  New in Django 4.0.

  The default command options to suppress in the help output. This should be a set of option names (e.g. `'--verbosity'`). The default values for the suppressed options are still passed.

### メソッド

`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` インスタンスを返します。これは:class:~argparse.ArgumentParser サブクラスで、Django用にいくつかカスタマイズされています。

  このメソッドをオーバーライドし、 `ArgumentParser` パラメータの `kwargs` を使って `super()` を呼び出すことでインスタンスをカスタマイズできます。

`BaseCommand.``add_arguments`(parser)

  コマンドに渡されたコマンドライン引数を操作するパーサーを追加するためのエントリポイントです。カスタム管理コマンドが受け取る位置引数およびオプション引数を追加するためにはこのメソッドをオーバーライドする必要が有ります。直接 `BaseCommand` を継承している場合は `super()` の呼び出しは必要有りません。

`BaseCommand.``get_version`()

  Djangoのバージョンを返します。これはすべての組み込みDjangoコマンドに対して正しいはずです。 ユーザー指定のコマンドは、このメソッドをオーバーライドして独自のバージョンを返すことができます。

`BaseCommand.``execute`(*args, **options)

  Tries to execute this command, performing system checks if needed (as controlled by the `requires_system_checks` attribute). If the command raises a `CommandError`, it's intercepted and printed to `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)

  Uses the system check framework to inspect the entire Django project for potential problems. Serious problems are raised as a `CommandError`; warnings are output to `stderr`; minor notifications are output to `stdout`.

  `app_configs` および `tags` が共に `None` であった場合、全てのシステムチェックが実行されます。`tags` はチェックタグ、例えば `compatibility` あるいは `models` 等、のリストとなります。

### `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)

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

If this exception is raised during the execution of a management command from a command line console, it will be caught and turned into a nicely-printed error message to the appropriate output stream (i.e., `stderr`); as a result, raising this exception (with a sensible description of the error) is the preferred way to indicate that something has gone wrong in the execution of a command. It accepts the optional `returncode` argument to customize the exit status for the management command to exit with, using `sys.exit()`.

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