# Documentation Django 3.1.9.dev

# Infrastructure de contrôle du système

L’infrastructure de contrôle du système est un ensemble de contrôles statiques pour valider les projets Django. Elle détecte les problèmes courants et fournit des conseils sur la façon de les corriger. L’infrastructure est extensible de sorte que vous pouvez facilement ajouter vos propres contrôles.

Les contrôles peuvent être déclenchées de manière explicite par la commande `check`. Les contrôles sont déclenchés implicitement avant la plupart des commandes, y compris `runserver` et `migrate`. Pour des raisons de performance, les contrôles ne sont pas effectués dans le contexte de la pile WSGI utilisée en mode déployé. Si vous avez besoin d’effectuer les contrôles systèmes sur le serveur de déploiement, appelez explicitement la commande `check`.

Les erreurs graves empêcheront les commandes de Django (comme `runserver`) de fonctionner, tout court. Les problèmes mineurs sont signalés dans la console. Si vous avez inspecté la cause d’un avertissement et que vous êtes content de l’ignorer, vous pouvez masquer des avertissements spécifiques en utilisant le réglage `SILENCED_SYSTEM_CHECKS` dans votre fichier de réglages du projet.

Une liste complète de tous les contrôles pouvant être levées par Django peuvent être trouvés dans la référence des contrôles système.

## Écrire vos propres contrôles

Le système est souple et vous permet d’écrire des fonctions qui effectuent tout autre type de contrôle dont vous auriez besoin. Ce qui suit est un exemple de squelette d’une fonction de contrôle :

    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

The check function must accept an `app_configs` argument; this argument is the list of applications that should be inspected. If `None`, the check must be run on all installed apps in the project. The `**kwargs` argument is required for future expansion.

### Messages

La fonction doit renvoyer une liste de messages. Si aucun problème n’est détecté suite à la vérification, la fonction de contrôle doit renvoyer une liste vide.

Les avertissements et les erreurs levés par la méthode de contrôle doivent être des instances de `CheckMessage`. Une instance de `CheckMessage` encapsule une seule erreur à signaler ou un seul avertissement. Elle fournit également des conseils et le contexte applicable au message, et un identifiant unique qui est utilisé à des fins de filtrage.

Le concept est très similaire aux messages du système de message ou de la journalisation. Les messages sont étiquettés avec un `level` indiquant la gravité du message.

Il existe également des raccourcis pour faciliter la création des messages avec les niveaux de base. Lorsque vous utilisez ces classes, vous pouvez omettre le paramètre `level` car il est sous-entendu par le nom de la classe.

- `Debug`
- `Info`
- `Warning`
- `Error`
- `Critical`

### Enregistrement et étiquetage des contrôles

Finalement, votre fonction de contrôle doit être explicitement inscrite dans le registre des contrôles systèmes. Les contrôles doivent être inscrits dans un fichier qui est chargé au moment du chargement de l’application. Par exemple, dans la méthode `AppConfig.ready()`.

`register`(*tags)(function)

Vous pouvez passer autant d’étiquettes que vous le souhaitez à `register` pour labeliser votre contrôle. L’étiquetage des contrôles est utile car elle vous permet de n’exécuter qu’un certain groupe de contrôles. Par exemple, pour enregistrer un contrôle de compatibilité, vous feriez l’appel suivant :

    from django.core.checks import register, Tags

    @register(Tags.compatibility)
    def my_check(app_configs, **kwargs):
        # ... perform compatibility checks and collect errors
        return errors

Vous pouvez inscrire des « contrôles de déploiement » qui ne sont applicables qu’à un fichier de réglages de production de la manière suivante :

    @register(Tags.security, deploy=True)
    def my_check(app_configs, **kwargs):
        ...

Ces contrôles ne seront exécutés que si l’option `check --deploy` est utilisée.

Vous pouvez aussi employer `register` comme une fonction au lieu d’un décorateur en lui transmettant un objet exécutable (habituellement une fonction) comme premier paramètre.

Le code ci-dessous est équivalent au code ci-dessus :

    def my_check(app_configs, **kwargs):
        ...
    register(my_check, Tags.security, deploy=True)

### Contrôles sur les champs, modèles, gestionnaires et bases de données

Dans certains cas, vous n’aurez pas besoin d’enregistrer votre fonction de contrôle – vous pouvez la greffer sur un enregistrement existant.

Les champs, les modèles, les gestionnaires de modèle et les moteurs de base de données implémentent tous une méthode `check()` qui est déjà enregistrée auprès du système de vérification. Si vous souhaitez ajouter des contrôles supplémentaires, vous pouvez étendre l’implémentation de la classe de base, effectuer tous contrôles supplémentaires nécessaires, et ajouter tous les messages à ceux générés par la classe de base. Il est recommandé que vous déléguiez chaque contrôle à des méthodes distinctes.

Prenons un exemple où vous implémentez un champ personnalisé nommé `RangedIntegerField`. Ce champ ajoute les arguments `min` et `max` au constructeur d”`IntegerField`. Vous pourriez ajouter une vérification afin de vous assurer que les utilisateurs fournissent une valeur min qui est inférieur ou égale à la valeur max. Le code suivant montre comment vous pouvez mettre en œuvre ce contrôle :

    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 []

Si vous vouliez ajouter des contrôles à un gestionnaire de modèle, vous prendriez la même approche avec votre sous-classe de `Manager`.

Si vous souhaitez ajouter un contrôle à une classe de modèle, l’approche est presque la même : la seule différence est que le contrôle est une méthode de classe, pas une méthode d’instance :

    class MyModel(models.Model):
        @classmethod
        def check(cls, **kwargs):
            errors = super().check(**kwargs)
            # ... your own checks ...
            return errors

### Écriture de tests

Les messages sont comparables. Cela vous permet d’écrire facilement des tests :

    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)