系统检查框架
系统检查框架是一组验证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
参数,因为它已经通过类名隐含。
注册和标记检查
最后,你的检查函数必须已经在系统检查注册表明确注册。检查应该在加载应用程序时加载文件中注册;比如,在 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)