系统检查框架 — Django 文档
系统检查框架
系统检查框架是一组用于验证 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)