系统检查框架

系统检查框架是一组用于验证Django项目的静态检查。它检测常见问题并提供如何修复这些问题的提示。框架是可扩展的,因此您可以轻松地添加自己的检查。

检查可以通过 check 命令。检查是在大多数命令之前隐式触发的,包括 runservermigrate . 出于性能原因,检查不会作为部署中使用的wsgi堆栈的一部分运行。如果需要在部署服务器上运行系统检查,请使用 check .

严重错误会阻止django命令(例如 runserver )从运行开始。小问题报告给控制台。如果您已经检查了警告的原因并乐于忽略它,则可以使用 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

检查功能 must 接受一个 app_configs 参数;此参数是应检查的应用程序列表。如果没有,必须进行检查 all 已在项目中安装应用程序。这个 **kwargs 参数是将来扩展所必需的。

信息

函数必须返回消息列表。如果检查没有发现问题,则检查功能必须返回空列表。

check方法引发的警告和错误必须是的实例 CheckMessage . 一个实例 CheckMessage 封装单个可报告的错误或警告。它还提供适用于消息的上下文和提示,以及用于筛选目的的唯一标识符。

这个概念与 message frameworklogging framework . 邮件标记为 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 . 这个字段增加了 minmax 的构造函数的参数 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)