# Django 5.0.9.dev20240806133106 ドキュメント

# システムチェックフレームワーク

システムチェックフレームワークは、Django プロジェクトを検証するための静的チェックのセットです。一般的な問題を検出し、それらを修正するヒントを提供します。このフレームワークは拡張性があり、独自のチェックを簡単に追加できます。

チェックは、`check` コマンドを介して明示的にトリガーできます。チェックは、`runserver` や `migrate` を含むほとんどのコマンドの前に暗黙的にトリガーされます。パフォーマンスのため、チェックはデプロイメントで使用される WSGI スタックの一部としては実行されません。デプロイメントサーバーでシステムチェックを実行する必要がある場合は、 `check` を使用して明示的にトリガーしてください。

重大なエラーは、Djangoのコマンド (たとえば `runserver`) の実行を完全に停止します。軽微な問題はコンソールに報告されます。警告の原因を調査し、無視しても問題ない場合は、プロジェクトの設定ファイルである `SILENCED_SYSTEM_CHECKS` 設定を使用して特定の警告を非表示にできます。

Djangoが発生させる可能性のあるすべてのチェックの完全なリストは、 システムチェックのリファレンス にあります。

## 独自のチェックを書く

フレームワークは柔軟で、必要に応じて任意の種類のチェックを実行する関数を書くことができます。以下は、例としてのスタブチェック関数です。

    from django.core.checks import Error, register

    @register()
    def example_check(app_configs, **kwargs):
        errors = []
        # ... your check logic here
        if check_failed:
            errors.append(
                Error(
                    "an error",
                    hint="A hint.",
                    obj=checked_object,
                    id="myapp.E001",
                )
            )
        return errors

チェック関数は、 必ず `app_configs` 引数を受け入れる必要があります。この引数は、調査されるべきアプリケーションのリストです。 `None` の場合、チェックはプロジェクト内の すべての インストールされたアプリで実行される必要があります。

チェックは `databases` キーワード引数を受け取ります。これは、データベースレベルの構成を調査するために使用される可能性のあるデータベースエイリアスのリストです。 `databases` が `None` の場合、チェックはどのデータベース接続も使用してはいけません。

`**kwargs` 引数は将来の拡張のために必要です。

### メッセージ

関数は、メッセージのリストを返さなければなりません。チェックの結果、問題が見つからない場合、チェック関数は空のリストを返さなければなりません。

チェックメソッドで発生させる警告やエラーは、必ず `CheckMessage` のインスタンスでなければなりません。`CheckMessage` のインスタンスは、1つの報告可能なエラーや警告をカプセル化します。また、メッセージに適用可能なコンテキストやヒント、フィルタリングの目的で使用される一意の識別子も提供します。

この概念は、 メッセージフレームワーク や ログフレームワーク のメッセージと非常に似ています。メッセージには、メッセージの深刻さを示す「レベル」が付けられます。

一般的なレベルのメッセージを簡単に作成するためのショートカットもあります。これらのクラスを使う場合、引数 `level` はクラス名によって省略できます。

- `Debug`
- `Info`
- `Warning`
- `Error`
- `Critical`

### チェックの登録とラベリング

最後に、チェック関数はシステムのチェックレジストリに明示的に登録する必要があります。チェックは、アプリケーションが読み込まれるときに読み込まれるファイル内に登録される必要があります。たとえば、 `AppConfig.ready()` メソッド内などです。

`register`(*tags)(function)

`register` には、チェックにラベルを付けるために必要な数のタグを渡すことができます。チェックにタグをつけると、特定のチェックグループだけを実行することができるので便利です。例えば、互換性チェックを登録するには、以下のように呼び出します:

    from django.core.checks import register, Tags

    @register(Tags.compatibility)
    def my_check(app_configs, **kwargs):
        # ... perform compatibility checks and collect errors
        return errors

以下のように、本番用の設定ファイルにのみ関係する「デプロイメントチェック」を登録できます:

    @register(Tags.security, deploy=True)
    def my_check(app_configs, **kwargs): ...

これらのチェックが行われるのは、`check --deploy` オプションが使用されたときだけです。

また、呼び出し可能オブジェクト（通常は関数）を `register` の第一引数に渡すことで、デコレータではなく関数として `register` を使用することもできます。

下記のコードは上記のコードと等価です:

    def my_check(app_configs, **kwargs): ...

    register(my_check, Tags.security, deploy=True)

### フィールド、モデル、マネージャ、およびデータベースのチェック

場合によっては、チェック機能を登録する必要はありません。既存の登録に「便乗させる」ことができます。

フィールド、モデル、モデルマネージャ、データベースバックエンドはすべて `check()` メソッドを実装しており、チェックフレームワークに登録されています。追加でチェックを行いたい場合は、基底クラスの実装を拡張して、必要な追加チェックを行い、基底クラスが生成したメッセージに追加します。各チェックは別々のメソッドに委譲することを推奨します。

`RangedIntegerField` というカスタムフィールドを実装する例を考えてみましょう。このフィールドは `IntegerField` のコンストラクタに `min` と `max` 引数を追加します。ユーザの min 値が max 値以下であることを確認するチェックを追加できます。次のコードスニペットは、このチェックを実装する方法を示しています:

    from django.core import checks
    from django.db import models

    class RangedIntegerField(models.IntegerField):
        def __init__(self, min=None, max=None, **kwargs):
            super().__init__(**kwargs)
            self.min = min
            self.max = max

        def check(self, **kwargs):
            # Call the superclass
            errors = super().check(**kwargs)

            # Do some custom checks and add messages to `errors`:
            errors.extend(self._check_min_max_values(**kwargs))

            # Return all errors and warnings
            return errors

        def _check_min_max_values(self, **kwargs):
            if self.min is not None and self.max is not None and self.min > self.max:
                return [
                    checks.Error(
                        "min greater than max.",
                        hint="Decrease min or increase max.",
                        obj=self,
                        id="myapp.E001",
                    )
                ]
            # When no error, return an empty list
            return []

モデルマネージャにチェックを追加したい場合は、 `Manager` のサブクラスで同じアプローチを取ります。

モデルクラスにチェックを追加したい場合、アプローチは ほとんど 同じです。唯一の違いは、チェックがインスタンスメソッドではなくクラスメソッドであるということです:

    class MyModel(models.Model):
        @classmethod
        def check(cls, **kwargs):
            errors = super().check(**kwargs)
            # ... your own checks ...
            return errors

### テストを書く

メッセージは比較可能なので、次のように簡単にテストを書くことができます。

    from django.core.checks import Error

    errors = checked_object.check()
    expected_errors = [
        Error(
            "an error",
            hint="A hint.",
            obj=checked_object,
            id="myapp.E001",
        )
    ]
    self.assertEqual(errors, expected_errors)

#### インテグレーションテストを書く

アプリケーションの読み込み時には特定のチェックを登録する必要があるため、システムチェックフレームワーク内での統合をテストするのが便利です。これは `call_command()` 関数を使うことで実現できます。

例えば、このテストは `SITE_ID` の設定が整数でなければならないことを示しています。これは組み込みの サイト フレームワークからのチェック のものです:

    from django.core.management import call_command
    from django.core.management.base import SystemCheckError
    from django.test import SimpleTestCase, modify_settings, override_settings

    class SystemCheckIntegrationTest(SimpleTestCase):
        @override_settings(SITE_ID="non_integer")
        @modify_settings(INSTALLED_APPS={"prepend": "django.contrib.sites"})
        def test_non_integer_site_id(self):
            message = "(sites.E101) The SITE_ID setting must be an integer."
            with self.assertRaisesMessage(SystemCheckError, message):
                call_command("check")

`ENABLE_ANALYTICS` というカスタム設定が `True` に設定されていない場合に、デプロイ時に警告を発行する以下のチェックを考えてみましょう:

    from django.conf import settings
    from django.core.checks import Warning, register

    @register("myapp", deploy=True)
    def check_enable_analytics_is_true_on_deploy(app_configs, **kwargs):
        errors = []
        if getattr(settings, "ENABLE_ANALYTICS", None) is not True:
            errors.append(
                Warning(
                    "The ENABLE_ANALYTICS setting should be set to True in deployment.",
                    id="myapp.W001",
                )
            )
        return errors

このチェックが `SystemCheckError` を発生させないことを考えると、以下のように、 `stderr` の出力に警告メッセージがあることをアサートできます:

    from io import StringIO

    from django.core.management import call_command
    from django.test import SimpleTestCase, override_settings

    class EnableAnalyticsDeploymentCheckTest(SimpleTestCase):
        @override_settings(ENABLE_ANALYTICS=None)
        def test_when_set_to_none(self):
            stderr = StringIO()
            call_command("check", "-t", "myapp", "--deploy", stderr=stderr)
            message = (
                "(myapp.W001) The ENABLE_ANALYTICS setting should be set "
                "to True in deployment."
            )
            self.assertIn(message, stderr.getvalue())