システムチェックフレームワーク
システムチェックフレームワークは、Djangoプロジェクトを検証するための一連の静的チェックです。 一般的な問題を検出し、それらを修正する方法のヒントを提供します。 フレームワークは拡張可能であるため、独自のチェックを簡単に追加できます。
チェックは、:djadmin: `check` コマンドを使用して明示的にトリガーできます。 チェックは、:djadmin: `runserver` や:djadmin:` migrate` を含むほとんどのコマンドの前に暗黙的にトリガーされます。 パフォーマンス上の理由から、展開で使用されるWSGIスタックの一部としてチェックは実行されません。 デプロイメントサーバーでシステムチェックを実行する必要がある場合は、:djadmin: `check` を使用して明示的にトリガーします。
重大なエラーが発生すると、Djangoコマンド(:djadmin: `runserver` など)がまったく実行されなくなります。 軽微な問題はコンソールに報告されます。 警告の原因を調べて無視してもかまわない場合は、プロジェクト設定ファイルの:setting: `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
引数は、将来の拡張に必要です。
メッセージ
関数はメッセージのリストを返す必要があります。 チェックの結果、問題が見つからなかった場合、チェック関数は空のリストを返す必要があります。
checkメソッドによって発生する警告とエラーは、 CheckMessage のインスタンスである必要があります。 CheckMessage のインスタンスは、単一の報告可能なエラーまたは警告をカプセル化します。 また、メッセージに適用可能なコンテキストとヒント、およびフィルタリングの目的で使用される一意の識別子も提供します。
概念は、メッセージフレームワークまたはロギングフレームワークからのメッセージと非常によく似ています。 メッセージには、メッセージの重大度を示すlevel
のタグが付けられます。
共通レベルのメッセージを簡単に作成するためのショートカットもあります。 これらのクラスを使用する場合、level
引数はクラス名によって暗示されるため、省略できます。
小切手の登録とラベル付け
最後に、チェック機能をシステムチェックレジストリに明示的に登録する必要があります。 小切手は、アプリケーションのロード時にロードされるファイルに登録する必要があります。 たとえば、 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
という名前のカスタムフィールドを実装している例を考えてみましょう。 このフィールドは、min
およびmax
引数をIntegerField
のコンストラクターに追加します。 ユーザーが最大値以下の最小値を提供することを確認するためのチェックを追加することをお勧めします。 次のコードスニペットは、このチェックを実装する方法を示しています。
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)