Система проверки фреймворка
Система проверки фреймворка — это набор статических проверок для валидации проектов Django. Она обнаруживает распространённые проблемы и предоставляет подсказки по их исправлению. Фреймворк расширяем, поэтому вы можете легко добавить свои собственные проверки.
Проверки можно явно активировать через команду check. Проверки неявно запускаются перед большинством команд, включая runserver и migrate. По соображениям производительности проверки не выполняются в рамках стека WSGI, используемого в развертывании. Если вам нужно запустить проверки системы на сервере развертывания, активируйте их явно с помощью check.
Серьёзные ошибки помешают запуску команд Django (например, runserver) вообще. Незначительные проблемы выводятся в консоль. Если вы изучили причину предупреждения и готовы его проигнорировать, вы можете скрыть определённые предупреждения, используя настройку 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, проверка должна быть запущена для всех установленных приложений в проекте. Аргумент **kwargs требуется для будущего расширения.
Сообщения
Функция должна возвращать список сообщений. Если в результате проверки проблем не обнаружено, функция проверки должна вернуть пустой список.
Предупреждения и ошибки, поднятые методом проверки, должны быть экземплярами 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(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 []
Если вы хотите добавить проверки к менеджеру модели, вы воспользуетесь тем же подходом для своего подкласса Manager.
Если вы хотите добавить проверку к классу модели, подход почти тот же: единственное отличие в том, что проверка является классовым методом, а не методом экземпляра:
class MyModel(models.Model):
@classmethod
def check(cls, **kwargs):
errors = super(MyModel, cls).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)
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.11/topics/checks/