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é)果中沒(méi)有發(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。