New in Django 1.7.
系統(tǒng)檢查框架是為了驗(yàn)證Django項(xiàng)目的一系列靜態(tài)檢查。它可以檢測(cè)到普遍的問(wèn)題,并且提供如何修復(fù)的提示。這個(gè)框架可以被擴(kuò)展,所以你可以輕易地添加你自己的檢查。
檢查可以由check
命令顯式觸發(fā)。檢查會(huì)在大多數(shù)命令之前隱式觸發(fā),包括runserver
和 migrate
。由于性能因素,檢查不作為在部署中使用的WSGI棧的一部分運(yùn)行。如果你需要在你的部署服務(wù)器上運(yùn)行系統(tǒng)檢查,顯式使用check
來(lái)觸發(fā)它們。
嚴(yán)重的錯(cuò)誤會(huì)完全阻止Django命令(像runserver
)的運(yùn)行。少數(shù)問(wèn)題會(huì)通過(guò)控制臺(tái)來(lái)報(bào)告。如果你檢查了警告的原因,并且愿意無(wú)視它,你可以使用你項(xiàng)目設(shè)置文件中的SILENCED_SYSTEM_CHECKS
設(shè)置,來(lái)隱藏特定的警告。
系統(tǒng)檢查參考中列出了所有Django可執(zhí)行的所有檢查。
這個(gè)框架十分靈活,允許你編寫函數(shù),執(zhí)行任何其他類型的所需檢查。下面是一個(gè)樁(stub)檢查函數(shù)的例子:
from django.core.checks import register
@register()
def example_check(app_configs, **kwargs):
errors = []
# ... your check logic here
return errors
檢查函數(shù)_必須_接受 app_configs
參數(shù);這個(gè)參數(shù)是要被檢查的應(yīng)用列表。如果是None,檢查會(huì)運(yùn)行在項(xiàng)目中_所有_安裝的應(yīng)用上。**kwargs
參數(shù)用于進(jìn)一步的擴(kuò)展。
這個(gè)函數(shù)必須返回消息的列表。如果檢查的結(jié)果中沒有發(fā)現(xiàn)問(wèn)題,檢查函數(shù)必須返回一個(gè)空列表。
class CheckMessage
(level, msg, hint, obj=None, id=None)
由檢查方法產(chǎn)生的警告和錯(cuò)誤必須是CheckMessage
的示例。CheckMessage
的實(shí)例封裝了一個(gè)可報(bào)告的錯(cuò)誤或者警告。它同時(shí)也提供了可應(yīng)用到消息的上下文或者提示,以及一個(gè)用于過(guò)濾的唯一的標(biāo)識(shí)符。
它的概念非常類似于消息框架或者 日志框架中的消息。消息使用表明其嚴(yán)重性的level
來(lái)標(biāo)記。
構(gòu)造器的參數(shù)是:
level
The severity of the message. Use one of the
predefined values: DEBUG
, INFO
, WARNING
, ERROR
,
CRITICAL
. If the level is greater or equal to ERROR
, then Django
will prevent management commands from executing. Messages with
level lower than ERROR
(i.e. warnings) are reported to the console,
but can be silenced.
msg
A short (less than 80 characters) string describing the problem. The string should not contain newlines.
hint
A single-line string providing a hint for fixing the problem. If no hint
can be provided, or the hint is self-evident from the error message, the
hint can be omitted, or a value of None
can be used.
obj
Optional. An object providing context for the message (for example, the
model where the problem was discovered). The object should be a model, field,
or manager or any other object that defines __str__
method (on
Python 2 you need to define __unicode__
method). The method is used while
reporting all messages and its result precedes the message.
id
Optional string. A unique identifier for the issue. Identifiers should
follow the pattern applabel.X001
, where X
is one of the letters
CEWID
, indicating the message severity (C
for criticals,
E
for errors and so). The number can be allocated by the application,
but should be unique within that application.
也有一些快捷方式,使得創(chuàng)建通用級(jí)別的消息變得簡(jiǎn)單。當(dāng)使用這些方法時(shí)你可以忽略level
參數(shù),因?yàn)樗深惷Q暗示。
class Debug
(msg, hint, obj=None, id=None)
class Info
(msg, hint, obj=None, id=None)
class Warning
(msg, hint, obj=None, id=None)
class Error
(msg, hint, obj=None, id=None)
class Critical
(msg, hint, obj=None, id=None)
消息是可比較的。你可以輕易地編寫測(cè)試:
from django.core.checks import Error
errors = checked_object.check()
expected_errors = [
Error(
'an error',
hint=None,
obj=checked_object,
id='myapp.E001',
)
]
self.assertEqual(errors, expected_errors)
最后,你的檢查函數(shù)必須使用系統(tǒng)檢查登記處來(lái)顯式注冊(cè)。
register
(*tags)(function)
你可以向 register
傳遞任意數(shù)量的標(biāo)簽來(lái)標(biāo)記你的檢查。Tagging checks is useful since it allows you to run only a certain group of checks. For example, to register a compatibility check, you would make the following call:
from django.core.checks import register, Tags
@register(Tags.compatibility)
def my_check(app_configs, **kwargs):
# ... perform compatibility checks and collect errors
return errors
New in Django 1.8.
你可以注冊(cè)“部署的檢查”,它們只和產(chǎn)品配置文件相關(guān),像這樣:
@register(Tags.security, deploy=True)
def my_check(app_configs, **kwargs):
...
這些檢查只在 --deploy
選項(xiàng)傳遞給check
命令的情況下運(yùn)行。
你也可以通過(guò)向register
傳遞一個(gè)可調(diào)用對(duì)象(通常是個(gè)函數(shù))作為第一個(gè)函數(shù),將 register
作為函數(shù)使用,而不是一個(gè)裝飾器。
下面的代碼和上面等價(jià):
def my_check(app_configs, **kwargs):
...
register(my_check, Tags.security, deploy=True)
Changed in Django 1.8:
添加了將注冊(cè)用作函數(shù)的功能。
在一些情況下,你并不需要注冊(cè)檢查函數(shù) -- 你可以直接使用現(xiàn)有的注冊(cè)。
字段、方法和模型管理器都實(shí)現(xiàn)了check()
方法,它已經(jīng)使用檢查框架注冊(cè)。如果你想要添加額外的檢查,你可以擴(kuò)展基類中的實(shí)現(xiàn),進(jìn)行任何你需要的額外檢查,并且將任何消息附加到基類生成的消息中。強(qiáng)烈推薦你將每個(gè)檢查分配到單獨(dú)的方法中。
考慮一個(gè)例子,其中你要實(shí)現(xiàn)一個(gè)叫做RangedIntegerField
的自定義字段。這個(gè)字段向IntegerField
的構(gòu)造器中添加min
和 max
參數(shù)。你可能想添加一個(gè)檢查,來(lái)確保用戶提供了小于等于最大值的最小值。下面的代碼段展示了如何實(shí)現(xiàn)這個(gè)檢查:
from django.core import checks
from django.db import models
class RangedIntegerField(models.IntegerField):
def __init__(self, min=None, max=None, **kwargs):
super(RangedIntegerField, self).__init__(**kwargs)
self.min = min
self.max = max
def check(self, **kwargs):
# Call the superclass
errors = super(RangedIntegerField, self).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 []
如果你想要向模型管理器添加檢查,應(yīng)該在你的Manager
的子類上執(zhí)行同樣的方法。
如果你想要向模型類添加檢查,方法也_大致_相同:唯一的不同是檢查是類方法,并不是實(shí)例方法:
class MyModel(models.Model):
@classmethod
def check(cls, **kwargs):
errors = super(MyModel, cls).check(**kwargs)
# ... your own checks ...
return errors
譯者:Django 文檔協(xié)作翻譯小組,原文:System check framework。
本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。
Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。