# Django 2.2.9.dev20191202104323 文档

# 系统检查框架

系统检查框架是一组验证Django项目的静态检查。 它检测到常见的问题，并提供了如何解决这些问题的提示。 该框架是可扩展的，所以你可以轻松地添加自己的检查。

通过 `check` 命令来显示的触发检查操作。检查会在大多数命令之前被隐式触发，包括 `runserver` 和 `migrate` 。出于性能原因，检查不会作为部署中使用的 WSGI 堆栈的一部分来运行。如果你需要在部署系统上运行系统检查，可以使用 `check` 来触发他们。

严重的错误将阻止 Django 命令（比如 `runserver`）运行。小问题将会在控制台上报告出来。如果你已经检查了警告的原因并愿意忽略它，你可以在 settings.py 文件里的 `SILENCED_SYSTEM_CHECKS` 设置隐藏指定的警告。

Django 引发的所有检查的完整列表在 System check reference 中可查。

## 编写自定义的检查

框架是可伸缩的，并且允许你编写函数来执行其他你需要的其他检查。举例：

    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` 参数；这个参数是应该被检查的应用程序列表。如果没有，检查必须运行在这个项目的所有 app 。未来扩展需要 `**kwargs` 参数。

### 消息

函数必须返回消息列表。如果检查结果没有发现问题，检查函数必须返回空列表。

警告和错误由必须是 `CheckMessage` 的检查方法引发。`CheckMessage` 的实例概括了错误或警告。它也提供适合消息的上下文和消息，和用来过滤目的的唯一标示。

这个概念与来自 message framework or the logging framework 的消息非常相似。消息标有 `level` ，标示消息的严重性。

也可以有快捷方式来简单创建公共级别的消息。当使用这些类你可以忽略 `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)

### 字段，模型，管理器和数据库检查

在某些情况下，你不需要注册检查函数——你可以使用现有的注册。

字段，模型，模型管理器和数据库后端都实现了一个检查方法，这个方法已经被检查框架注册。如果你想添加其他检查，你可以在基类上扩展实现，完成任何你需要的检查，将任何消息添加到基类生成的消息。建议你将每个检查委派给不同方法。

考虑一个例子，你正在实现一个自定义字段 `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)