# Django 6.0.5 documentation

# Ramverk för systemkontroll

Ramverket System Check är en uppsättning statiska kontroller för validering av Django-projekt. Det upptäcker vanliga problem och ger tips om hur man åtgärdar dem. Ramverket är utbyggbart så att du enkelt kan lägga till dina egna kontroller.

Kontroller kan utlösas explicit via kommandot `check`. Kontroller utlöses implicit före de flesta kommandon, inklusive `runserver` och `migrate`. Av prestandaskäl körs inte kontrollerna som en del av WSGI-stacken som används vid distributionen. Om du behöver köra systemkontroller på din distributionsserver ska du utlösa dem explicit med `check`.

Allvarliga fel förhindrar Django-kommandon (t.ex. `runserver`) från att köras överhuvudtaget. Mindre problem rapporteras till konsolen. Om du har undersökt orsaken till en varning och gärna ignorerar den, kan du dölja specifika varningar med hjälp av inställningen `SILENCED_SYSTEM_CHECKS` i projektets inställningsfil.

En fullständig lista över alla kontroller som kan ställas in av Django finns i Systemkontrollreferens.

## Skriva ut dina egna checkar

Ramverket är flexibelt och låter dig skriva funktioner som utför alla andra typer av kontroller som du kan tänkas behöva. Följande är ett exempel på en stubkontrollfunktion:

    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

Check-funktionen måste acceptera ett `app_configs`-argument; detta argument är listan över applikationer som ska inspekteras. Om `None`, måste kontrollen köras på alla installerade appar i projektet.

Kontrollen får ett argument i form av nyckelordet `databases`. Detta är en lista över databasalias vars anslutningar kan användas för att inspektera konfigurationen på databasnivå. Om `databases` är `None` får kontrollen inte använda några databasanslutningar.

Argumentet `**kwargs` är nödvändigt för framtida expansion.

### Meddelanden

Funktionen måste returnera en lista med meddelanden. Om inga problem hittas som ett resultat av kontrollen, måste check-funktionen returnera en tom lista.

De varningar och fel som checkmetoden ger upphov till måste vara instanser av `CheckMessage`. En instans av `CheckMessage` kapslar in ett enda rapporterbart fel eller varning. Det ger också sammanhang och tips som är tillämpliga på meddelandet och en unik identifierare som används för filtreringsändamål.

Konceptet är mycket likt meddelanden från message framework eller logging framework. Meddelanden taggas med en `nivå` som anger hur allvarligt meddelandet är.

Det finns också genvägar som gör det enklare att skapa meddelanden med gemensamma nivåer. När du använder dessa klasser kan du utelämna argumentet `level` eftersom det är underförstått av klassnamnet.

- `Debug`

- `Info`

- `Warning`

- `Fel`

- `Kritisk`

### Registrering och märkning av kontroller

Slutligen måste din kontrollfunktion registreras uttryckligen med systemets kontrollregister. Kontroller bör registreras i en fil som laddas när din applikation laddas; till exempel i metoden `AppConfig.ready()`.

register(*tags)(function)

Du kan skicka så många taggar till `register` som du vill för att märka din kontroll. Att märka kontroller är användbart eftersom det gör att du bara kan köra en viss grupp av kontroller. Om du t.ex. vill registrera en kompatibilitetskontroll gör du följande anrop:

    from django.core.checks import register, Tags

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

Du kan registrera ”deployment checks” som endast är relevanta för en produktionsinställningsfil på följande sätt:

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

Dessa kontroller kommer endast att köras om alternativet `check --deploy` används.

Du kan också använda `register` som en funktion i stället för en dekorator genom att skicka ett anropsbart objekt (vanligtvis en funktion) som första argument till `register`.

Koden nedan är likvärdig med koden ovan:

    def my_check(app_configs, **kwargs): ...

    register(my_check, Tags.security, deploy=True)

### Field, constraint, model, manager, template engine, task, and database checks

I vissa fall behöver du inte registrera din checkfunktion - du kan använda dig av en befintlig registrering.

Fields, constraints, models, model managers, template engines, task backends, and database backends all implement a `check()` method that is already registered with the check framework. If you want to add extra checks, you can extend the implementation on the base class, perform any extra checks you need, and append any messages to those generated by the base class. It’s recommended that you delegate each check to separate methods.

Tänk på ett exempel där du implementerar ett anpassat fält med namnet `RangedIntegerField`. Det här fältet lägger till argumenten `min` och `max` i konstruktören för `IntegerField`. Du kanske vill lägga till en kontroll för att se till att användarna anger ett min-värde som är mindre än eller lika med max-värdet. Följande kodutdrag visar hur du kan implementera denna kontroll:

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

Om du vill lägga till kontroller till en modellhanterare skulle du använda samma tillvägagångssätt på din underklass av `Manager`.

Om du vill lägga till en kontroll i en modellklass är tillvägagångssättet nästan detsamma: den enda skillnaden är att kontrollen är en klassmetod, inte en instansmetod:

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

Changed in Django 6.0:

In older versions, constraints didn’t implement a `check()` method.

### Skriva tester

Meddelanden är jämförbara. Det gör att du enkelt kan skriva tester:

    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)

#### Skriva integrationstester

Med tanke på behovet av att registrera vissa kontroller när applikationen laddas kan det vara användbart att testa deras integration inom ramverket för systemkontroller. Detta kan åstadkommas genom att använda funktionen `call_command()`.

Det här testet visar till exempel att inställningen `SITE_ID` måste vara ett heltal, en inbyggd check från sites-ramverket:

    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")

Tänk på följande kontroll som ger en varning vid distribution om en anpassad inställning med namnet `ENABLE_ANALYTICS` inte är inställd på `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

Med tanke på att denna kontroll inte kommer att ge upphov till ett `SystemCheckError`, kan förekomsten av varningsmeddelandet i `stderr`-utdata hävdas på följande sätt:

    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())