Spec-Zone.ru › Django 5.1

Система проверки системы

Система проверки системы — это набор статических проверок для проверки проектов 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, проверка должна выполняться на всех установленных приложениях в проекте.

Функция проверки получит ключевой аргумент databases. Это список псевдонимов баз данных, подключения к которым могут быть использованы для проверки конфигурации уровня базы данных. Если databases равен None, проверка не должна использовать никакие подключения к базам данных.

Аргумент **kwargs необходим для дальнейшего расширения.

Сообщения

Функция должна вернуть список сообщений. Если в результате проверки проблем не обнаружено, функция проверки должна вернуть пустой список.

Предупреждения и ошибки, поднятые методом проверки, должны быть экземплярами CheckMessage. Экземпляр CheckMessage инкапсулирует одну отслеживаемую ошибку или предупреждение. Он также предоставляет контекст и подсказки, относящиеся к сообщению, и уникальный идентификатор, используемый для целей фильтрации.

Концепция очень похожа на сообщения из системы сообщений или системы логирования. Сообщения помечены тегом level, указывающим на уровень важности сообщения.

Существуют также сокращения для упрощения создания сообщений с общими уровнями. При использовании этих классов вы можете опустить аргумент level, поскольку он подразумевается именем класса.

  • Debug
  • Info
  • Warning
  • Error
  • Critical

Регистрация и маркировка проверок

Наконец, ваша функция проверки должна быть явно зарегистрирована в реестре проверки системы. Проверки должны быть зарегистрированы в файле, который загружается при загрузке вашего приложения; например, в методе 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
Изменено в Django 5.1:

В более старых версиях движки шаблонов не реализовывали метод check().

Написание тестов

Сообщения сравнимы. Это позволяет легко писать тесты:

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)

Написание интеграционных тестов

Учитывая необходимость регистрации определённых проверок при загрузке приложения, может быть полезно проверить их интеграцию в рамках системы проверок. Это можно сделать, используя функцию call_command().

Например, этот тест демонстрирует, что настройка SITE_ID должна быть целым числом, встроенной проверкой из системы проверок сайтов:

from django.core.management import call_command
from django.core.management.base import SystemCheckError
from django.test import SimpleTestCase, modify_settings, override_settings


class SystemCheckIntegrationTest(SimpleTestCase):
    @override_settings(SITE_ID="non_integer")
    @modify_settings(INSTALLED_APPS={"prepend": "django.contrib.sites"})
    def test_non_integer_site_id(self):
        message = "(sites.E101) The SITE_ID setting must be an integer."
        with self.assertRaisesMessage(SystemCheckError, message):
            call_command("check")

Рассмотрим следующую проверку, которая выводит предупреждение при развертывании, если пользовательская настройка с именем ENABLE_ANALYTICS не установлена в значение True:

from django.conf import settings
from django.core.checks import Warning, register


@register("myapp", deploy=True)
def check_enable_analytics_is_true_on_deploy(app_configs, **kwargs):
    errors = []
    if getattr(settings, "ENABLE_ANALYTICS", None) is not True:
        errors.append(
            Warning(
                "The ENABLE_ANALYTICS setting should be set to True in deployment.",
                id="myapp.W001",
            )
        )
    return errors

Поскольку эта проверка не поднимет SystemCheckError, наличие сообщения предупреждения в выводе stderr можно проверить следующим образом:

from io import StringIO

from django.core.management import call_command
from django.test import SimpleTestCase, override_settings


class EnableAnalyticsDeploymentCheckTest(SimpleTestCase):
    @override_settings(ENABLE_ANALYTICS=None)
    def test_when_set_to_none(self):
        stderr = StringIO()
        call_command("check", "-t", "myapp", "--deploy", stderr=stderr)
        message = (
            "(myapp.W001) The ENABLE_ANALYTICS setting should be set "
            "to True in deployment."
        )
        self.assertIn(message, stderr.getvalue())

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/topics/checks/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API