---
title: "カスタム django-admin コマンドの実装"
version: 2.0
locale: ja
source: https://docs.djangoproject.com/ja/2.0/howto/custom-management-commands/
canonical: https://djangodocs.dev/ja/2.0/howto/custom-management-commands/
---
# カスタム `django-admin` コマンドの実装

`manage.py` を用いることで独自のアクションを登録する事ができます。例として、あなたが配布している Django アプリケーションに `manage.py` アクションを追加したくなったとします。このドキュメントでは、[このチュートリアル](/ja/2.0/intro/tutorial01/) で作成した `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
```

この例では、`closepoll` コマンドは `polls` アプリケーションを [`INSTALLED_APPS`](/ja/2.0/ref/settings/#std-setting-INSTALLED_APPS) に含むプロジェクト全てで利用できるようになります。

`_private.py` モジュールは管理コマンドとして利用できません。

`closepoll.py` モジュールには一つだけ満たすべき要件が有ります。 -- [`BaseCommand`](#django.core.management.BaseCommand) クラスもしくはその [サブクラス](#ref-basecommand-subclasses) の一つを継承した `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_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))
```

> **Note**
>
> 管理コマンドを利用してコンソールへの標準出力を行いたい場合、`stdout` と `stderr` に直接文字列を渡すのではなく、`self.stdout` および `self.stderr` を利用するべきです。このようなプロキシパターンを用いることで、カスタム管理コマンドのテストをずっと簡単にする事ができます。改行文字でメッセージを終了させる必要が無い、`ending` パラメータを定義しなければ自動的に改行される、事にも注意してください。:
>
> ```
> self.stdout.write("Unterminated line", ending='')
> ```

新たに作成したカスタムコマンドは `python manage.py closepoll <poll_id>` と実行する事で利用できます。

`handle()` メソッドは一つ以上の `poll_ids` を受け取り、それぞれに対応した `poll.opened` を `False` にセットします。もしコマンドの利用者が存在しない poll を指定した場合、[`CommandError`](#django.core.management.CommandError) 例外が発生します。`poll.opened` 属性は元の [チュートリアル](/ja/2.0/intro/tutorial01/) には存在しないので、この例では `polls.models.Question` モデルに追加しました。

## 省略可能な引数を受け入れる

ここまで実装した `closepoll` に対し、別途コマンドラインオプションを受け取ることで指定された投票を閉じる代わりに削除するよう機能追加する事も容易に可能です。これらのオプション機能は [`add_arguments()`](#django.core.management.BaseCommand.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',
            help='Delete poll instead of closing it',
        )

    def handle(self, *args, **options):
        # ...
        if options['delete']:
            poll.delete()
        # ...
```

オプション(例では `delete`)は handle メソッドで辞書型変数の引数として利用可能です。`add_argument` の利用についてより詳細な情報を得るには Python 公式ドキュメントの [`argparse`](https://docs.python.org/3/library/argparse.html#module-argparse) を参照してください。

独自のコマンドラインオプションを追加できるのに加え、[management commands](/ja/2.0/ref/django-admin/) に定義された [`--verbosity`](/ja/2.0/ref/django-admin/#cmdoption-verbosity) や [`--traceback`](/ja/2.0/ref/django-admin/#cmdoption-traceback) といったオプションも標準で利用できます。

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

標準では、[`BaseCommand.execute()`](#django.core.management.BaseCommand.execute) メソッドは、Django に含まれる一部のコマンドが、プロジェクト全体を通じて中立な文字列の言語を必要とするタスク(例えばエンドユーザーに対するコンテンツ出力やデータベースへのデータ投入など)を実行するため、翻訳処理を無効化しています。

何らかの理由でカスタム管理コマンドから特定のロケールを利用する必要が有る場合は、I18N をサポートしているコードから提供される関数を利用している [`handle()`](#django.core.management.BaseCommand.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`](#django.core.management.BaseCommand.leave_locale_alone) オプションを利用する事で望む結果を得ることができます。

ただし先に述べた状況に取り組む場合、多様なロケールでのシステム管理コマンドの実行には細心の注意を払う必要が有る事を考慮しておくべきです。すなわち以下に示す点に注意してください:

- そのコマンドが実行される際は設定値 [`USE_I18N`](/ja/2.0/ref/settings/#std-setting-USE_I18N) が常に `True` である事を確認してください。(これは Django を処理する動的ランタイム環境が翻訳機能を即座に無効化する事に起因する潜在的な問題の好例です)
- 作成したコマンドとロケールが変わる事で振る舞いが変わるコードをレビューし、作成したコマンドにおいて予想される振る舞いへの影響を評価してください。

## テスト

カスタム管理コマンドのテストに関する情報は [テストに関するページ](/ja/2.0/topics/testing/tools/#topics-testing-management-commands) で得ることができます。

## Overriding commands

Django registers the built-in commands and then searches for commands in
[`INSTALLED_APPS`](/ja/2.0/ref/settings/#std-setting-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`](/ja/2.0/ref/settings/#std-setting-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`](/ja/2.0/ref/settings/#std-setting-INSTALLED_APPS)) which imports the `Command` of the overridden
command.

## Command オブジェクト

#### `class BaseCommand`

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

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

[`BaseCommand`](#django.core.management.BaseCommand) クラスのサブクラス化には [`handle()`](#django.core.management.BaseCommand.handle) メソッドの実装が必要です。

### 属性

属性は全て派生クラスでセットでき、[`BaseCommand`](#django.core.management.BaseCommand) クラスの [サブクラス](#ref-basecommand-subclasses) で利用可能です。

#### `BaseCommand.help`

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

#### `BaseCommand.missing_args_message`

入力が必須の位置引数を定義しており、その引数が失われている場合に返すエラーメッセージを任意に設定する事ができます。デフォルトの出力は [`argparse`](https://docs.python.org/3/library/argparse.html#module-argparse) による出力("too few arguments")です。

#### `BaseCommand.output_transaction`

A boolean indicating whether the command outputs SQL statements; if
`True`, the output will automatically be wrapped with `BEGIN;` and
`COMMIT;`. Default value is `False`.

#### `BaseCommand.requires_migrations_checks`

ブーリアン値。`True` の場合、ディスク上に存在する一連のマイグレーション定義がデータベース上に保存されたマイグレーション定義とマッチしない場合に警告を出力します。この警告はコマンドの実行を停止させる物ではありません。デフォルトの値は `False` です。

#### `BaseCommand.requires_system_checks`

ブーリアン値。`True` の場合、コマンド実行前に Django プロジェクト全体が潜在的な問題を抱えていないかチェックされます。デフォルトの値は `True` です。

#### `BaseCommand.leave_locale_alone`

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.auth`](/ja/2.0/topics/auth/#module-django.contrib.auth) permissions) as
activating any locale might cause unintended effects. See the [Management
commands and locales](#id1) section above for further details.

#### `BaseCommand.style`

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

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

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

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

### メソッド

[`BaseCommand`](#django.core.management.BaseCommand) has a few methods that can be overridden but only
the [`handle()`](#django.core.management.BaseCommand.handle) method must be implemented.

> **サブクラス内でのコンストラクタの実装**
>
> [`BaseCommand`](#django.core.management.BaseCommand) を継承したサブクラス内で `__init__` を実装する場合、[`BaseCommand`](#django.core.management.BaseCommand) の `__init__` を呼び出す必要が有ります:
>
> ```
> class Command(BaseCommand):
>     def __init__(self, *args, **kwargs):
>         super().__init__(*args, **kwargs)
>         # ...
> ```

#### `BaseCommand.add_arguments(parser)`

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

#### `BaseCommand.get_version()`

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

コマンドを実行し、必要とされた場合([`requires_system_checks`](#django.core.management.BaseCommand.requires_system_checks) 属性によって設定可能)システムチェックを行います。コマンドが [`CommandError`](#django.core.management.CommandError) 例外を発生させた場合は、実行を中断して stderr に出力します。

> **コード中での管理コマンドの呼び出し**
>
> カスタム管理コマンドを実行するためにコード中から　`execute()` を直接呼び出す事は避けてください。代わりに [`call_command()`](/ja/2.0/ref/django-admin/#django.core.management.call_command) を利用してください。

#### `BaseCommand.handle(*args, **options)`

コマンドにおける実際の処理内容。サブクラスはこのメソッドを実装しなくてはならない。

It may return a string which will be printed to `stdout` (wrapped
by `BEGIN;` and `COMMIT;` if [`output_transaction`](#django.core.management.BaseCommand.output_transaction) is `True`).

#### `BaseCommand.check(app_configs=None, tags=None, display_num_errors=False)`

潜在的な問題のために Django プロジェクト全体を検証するシステムチェックフレームワークを利用します。致命的な問題は [`CommandError`](#django.core.management.CommandError) 例外を発生し、警告は stderr への出力、重要でない通知は stdout への出力となります。

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

### `BaseCommand` のサブクラス

#### `class AppCommand`

一つ以上のインストールされたアプリケーションラベルを引数として受け取り、それぞれに対して何らかの処理を行う管理コマンド。

[`handle()`](#django.core.management.BaseCommand.handle) を実装する代わりに、サブクラスでは、アプリケーション毎に一度ずつだけ呼び出される [`handle_app_config()`](#django.core.management.AppCommand.handle_app_config) を実装する必要が有ります。

#### `AppCommand.handle_app_config(app_config, **options)`

コマンドラインで渡されたアプリケーションラベル個々に対応している [`AppConfig`](/ja/2.0/ref/applications/#django.apps.AppConfig) のインスタンスである `app_config` に応じたコマンドの処理を行います。

#### `class LabelCommand`

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()`](#django.core.management.BaseCommand.handle), subclasses must implement
[`handle_label()`](#django.core.management.LabelCommand.handle_label), which will be called once for each label.

#### `LabelCommand.label`

コマンドに渡される任意引数について記述した文字列。この文字列はコマンドの使用法やエラーメッセージに利用します。デフォルトは `'label'` です。

#### `LabelCommand.handle_label(label, **options)`

コマンドラインに渡された文字列である `label` に対応したコマンドの処理を行います。

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

#### `exception CommandError`

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

コマンドラインコンソールから管理コマンドを実行中にこの例外が送出された場合、その例外は捕捉されて適切な出力ストリーム(例えば stderr 等)に整形されたエラーメッセージを表示させます。結果として、例外の送出は(エラーに関する明快な記述と併せて)コマンド実行中何らかの問題が発生した場合に状態を示す好ましい方法となります。

[`call_command()`](/ja/2.0/ref/django-admin/#django.core.management.call_command) を介して管理コマンドが実行された場合は、例外の捕捉をするかどうかは実装に依存します。
