# Django 6.0.7 documentation

# Hur man skapar egna kommandon för `django-admin`

Program kan registrera sina egna åtgärder med `manage.py`. Du kanske till exempel vill lägga till en `manage.py`-åtgärd för en Django-app som du distribuerar. I det här dokumentet kommer vi att bygga ett anpassat `closepoll`-kommando för applikationen `polls` från tutorial.

För att göra detta, lägg till en `management/commands` katalog i applikationen. Django kommer att registrera ett `manage.py`-kommando för varje Python-modul i den katalogen vars namn inte börjar med ett understreck. Till exempel:

    polls/
        __init__.py
        models.py
        management/
            __init__.py
            commands/
                __init__.py
                _private.py
                closepoll.py
        tests.py
        views.py

I det här exemplet kommer kommandot `closepoll` att göras tillgängligt för alla projekt som innehåller applikationen `polls` i `INSTALLED_APPS`.

Modulen `_private.py` kommer inte att vara tillgänglig som ett hanteringskommando.

Modulen `closepoll.py` har bara ett krav – den måste definiera en klass `Command` som utökar `BaseCommand` eller en av dess subclasses.

Fristående skript

Anpassade hanteringskommandon är särskilt användbara för att köra fristående skript eller för skript som regelbundet körs från UNIX crontab eller från kontrollpanelen för schemalagda uppgifter i Windows.

För att implementera kommandot, redigera `polls/management/commands/closepoll.py` så att det ser ut så här:

    from django.core.management.base import BaseCommand, CommandError
    from polls.models import Question as Poll

    class Command(BaseCommand):
        help = "Closes the specified poll for voting"

        def add_arguments(self, parser):
            parser.add_argument("poll_ids", nargs="+", type=int)

        def handle(self, *args, **options):
            for poll_id in options["poll_ids"]:
                try:
                    poll = Poll.objects.get(pk=poll_id)
                except Poll.DoesNotExist:
                    raise CommandError('Poll "%s" does not exist' % poll_id)

                poll.opened = False
                poll.save()

                self.stdout.write(
                    self.style.SUCCESS('Successfully closed poll "%s"' % poll_id)
                )

Observera

När du använder hanteringskommandon och vill tillhandahålla konsolutdata bör du skriva till `self.stdout` och `self.stderr` i stället för att skriva ut direkt till `stdout` och `stderr`. Genom att använda dessa proxyer blir det mycket enklare att testa ditt anpassade kommando. Observera också att du inte behöver avsluta meddelanden med ett nytt radtecken, det läggs till automatiskt om du inte anger parametern `ending`:

    self.stdout.write("Unterminated line", ending="")

Det nya anpassade kommandot kan anropas med hjälp av `python manage.py closepoll <poll_ids>`.

Metoden `handle()` tar ett eller flera `poll_ids` och sätter `poll.opened` till `False` för varje. Om användaren refererar till en icke-existerande enkät genereras ett `CommandError`. Attributet `poll.opened` finns inte i tutorial och lades till i `polls.models.Question` för detta exempel.

## Acceptera valfria argument

Samma `closepoll` kan enkelt modifieras för att ta bort en viss undersökning i stället för att stänga den genom att acceptera ytterligare kommandoradsalternativ. Dessa anpassade alternativ kan läggas till i `add_arguments()`-metoden så här:

    class Command(BaseCommand):
        def add_arguments(self, parser):
            # Positional arguments
            parser.add_argument("poll_ids", nargs="+", type=int)

            # Named (optional) arguments
            parser.add_argument(
                "--delete",
                action="store_true",
                help="Delete poll instead of closing it",
            )

        def handle(self, *args, **options):
            # ...
            if options["delete"]:
                poll.delete()
            # ...

Alternativet (`delete` i vårt exempel) finns tillgängligt i parametern options dict i metoden handle. Se Python-dokumentationen för `argparse` för mer information om användningen av `add_argument`.

Förutom att kunna lägga till egna kommandoradsalternativ kan alla hanteringskommandon acceptera vissa standardalternativ som `--verbosity` och `--traceback`.

## Hanteringskommandon och lokala språk

Som standard utförs hanteringskommandon med den aktuella aktiva språkdräkten.

Om ditt anpassade hanteringskommando av någon anledning måste köras utan en aktiv lokal (t.ex. för att förhindra att översatt innehåll infogas i databasen), avaktiverar du översättningar med hjälp av dekoratorn `@no_translations` på din `handle()`-metod:

    from django.core.management.base import BaseCommand, no_translations

    class Command(BaseCommand):
        ...

        @no_translations
        def handle(self, *args, **options): ...

Eftersom avaktivering av översättning kräver tillgång till konfigurerade inställningar kan dekoratorn inte användas för kommandon som fungerar utan konfigurerade inställningar.

## Testar

Information om hur du testar anpassade hanteringskommandon finns i testing docs.

## Åsidosätta kommandon

Django registrerar de inbyggda kommandona och söker sedan efter kommandon i `INSTALLED_APPS` i omvänd ordning. Under sökningen, om ett kommandonamn duplicerar ett redan registrerat kommando, åsidosätter det nyupptäckta kommandot det första.

Med andra ord, för att åsidosätta ett kommando måste det nya kommandot ha samma namn och dess app måste ligga före det åsidosatta kommandots app i `INSTALLED_APPS`.

Hanteringskommandon från tredjepartsappar som oavsiktligt har åsidosatts kan göras tillgängliga under ett nytt namn genom att skapa ett nytt kommando i en av projektets appar (rangordnat före tredjepartsappen i `INSTALLED_APPS`) som importerar `Command` för det åsidosatta kommandot.

## Kommandoobjekt

class BaseCommand

Basklassen som alla managementkommandon i slutändan härrör från.

Använd den här klassen om du vill ha tillgång till alla mekanismer som analyserar kommandoradsargumenten och räknar ut vilken kod som ska anropas som svar; om du inte behöver ändra något av det beteendet, överväg att använda en av dess subclasses.

Underklassning av klassen `BaseCommand` kräver att du implementerar metoden `handle()`.

### Attribut

Alla attribut kan ställas in i din härledda klass och kan användas i `BaseCommand`’s subclasses.

BaseCommand.help

  En kort beskrivning av kommandot som kommer att skrivas ut i hjälpmeddelandet när användaren kör kommandot `python manage.py help <command>`.

BaseCommand.missing_args_message

  Om ditt kommando definierar obligatoriska positionsargument kan du anpassa det felmeddelande som returneras om argument saknas. Standardmeddelandet genereras av `argparse` (”för få argument”).

BaseCommand.output_transaction

  Ett booleskt värde som anger om kommandot matar ut SQL-satser; om `True`, kommer utdata automatiskt att omslutas av `BEGIN;` och `COMMIT;`. Standardvärdet är `False`.

BaseCommand.requires_migrations_checks

  Ett boolean; om `True`, skriver kommandot ut en varning om uppsättningen migreringar på disken inte stämmer överens med migreringarna i databasen. En varning hindrar inte kommandot från att utföras. Standardvärdet är `False`.

BaseCommand.requires_system_checks

  En lista eller tupel av taggar, t.ex. `[Tags.staticfiles, Tags.models]`. Systemkontroller registrerade i de valda taggarna kommer att kontrolleras för fel innan kommandot utförs. Värdet `'__all__'` kan användas för att ange att alla systemkontroller ska utföras. Standardvärdet är `'__all__'`.

BaseCommand.style

  Ett instansattribut som hjälper till att skapa färgade utdata när du skriver till `stdout` eller `stderr`. Till exempel:

      self.stdout.write(self.style.SUCCESS("..."))

  Se Syntax färgläggning för att lära dig hur du ändrar färgpaletten och för att se de tillgängliga stilarna (använd versaler av ”rollerna” som beskrivs i det avsnittet).

  Om du anger alternativet `--no-color` när du kör ditt kommando kommer alla anrop av `self.style()` att returnera originalsträngen ofärgad.

BaseCommand.suppressed_base_arguments

  Standardkommandovalternativen som ska undertryckas i hjälputmatningen. Detta bör vara en uppsättning alternativnamn (t.ex. `'--verbosity'`). Standardvärdena för de undertryckta alternativen skickas fortfarande.

### Metoder

`BaseCommand` har några metoder som kan åsidosättas men endast metoden `handle()` måste implementeras.

Implementera en konstruktor i en subklass

Om du implementerar `__init__` i din subklass av `BaseCommand` måste du anropa `BaseCommand`:s `__init__`:

    class Command(BaseCommand):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # ...

BaseCommand.create_parser(prog_name, subcommand, **kwargs)

  Returnerar en `CommandParser`-instans, som är en `ArgumentParser`-underklass med några anpassningar för Django.

  Du kan anpassa instansen genom att åsidosätta den här metoden och anropa `super()` med `kwargs` av `ArgumentParser`-parametrar.

BaseCommand.add_arguments(parser)

  Ingångspunkt för att lägga till parserargument för att hantera kommandoradsargument som skickas till kommandot. Anpassade kommandon bör åsidosätta denna metod för att lägga till både positionella och valfria argument som accepteras av kommandot. Anrop av `super()` behövs inte vid direkt subklassning av `BaseCommand`.

BaseCommand.get_version()

  Returnerar Django-versionen, som bör vara korrekt för alla inbyggda Django-kommandon. Användartillhandahållna kommandon kan åsidosätta den här metoden för att returnera sin egen version.

BaseCommand.execute(*args, **options)

  Försöker köra kommandot och utför systemkontroller om det behövs (styrs av attributet `requires_system_checks`). Om kommandot ger upphov till ett `CommandError`, fångas det upp och skrivs ut till `stderr`.

Anropa ett management-kommando i din kod

`execute()` ska inte anropas direkt från din kod för att utföra ett kommando. Använd `call_command()` istället.

BaseCommand.handle(*args, **options)

  Den faktiska logiken i kommandot. Underklasser måste implementera denna metod.

  Den kan returnera en sträng som kommer att skrivas ut till `stdout` (omsluten av `BEGIN;` och `COMMIT;` om `output_transaction` är `True`).

BaseCommand.check(app_configs=None, tags=None, display_num_errors=False, include_deployment_checks=False, fail_level=checks.ERROR, databases=None)

  Använder ramverket för systemkontroll för att inspektera hela Django-projektet för potentiella problem. Allvarliga problem tas upp som ett `CommandError`; varningar skickas ut till `stderr`; mindre meddelanden skickas ut till `stdout`.

  Om `app_configs` och `tags` båda är `None` utförs alla systemkontroller utom distributions- och databasrelaterade kontroller. `tags` kan vara en lista med kontrolltaggar, t.ex. `compatibility` eller `models`.

  Du kan ange `include_deployment_checks=True` för att även utföra deployment-kontroller och en lista med databasalias i `databases` för att köra databasrelaterade kontroller mot dem.

BaseCommand.get_check_kwargs(options)

  Tillhandahåller kwargs för anropet till `check()`, inklusive omvandling av värdet av `requires_system_checks` till kwarg `tag`.

  Åsidosätt denna metod för att ändra de värden som anges i `check()`. Om du t.ex. vill välja databasrelaterade kontroller kan du åsidosätta `get_check_kwargs()` enligt följande:

      def get_check_kwargs(self, options):
          kwargs = super().get_check_kwargs(options)
          return {**kwargs, "databases": [options["database"]]}

### underklasser till `BaseCommand`

class AppCommand

Ett managementkommando som tar en eller flera installerade applikationsetiketter som argument och gör något med var och en av dem.

I stället för att implementera `handle()` måste underklasser implementera `handle_app_config()`, som anropas en gång för varje applikation.

AppCommand.handle_app_config(app_config, **options)

  Utför kommandots åtgärder för `app_config`, som kommer att vara en `AppConfig`-instans som motsvarar en applikationsetikett som anges på kommandoraden.

class LabelCommand

Ett managementkommando som tar ett eller flera godtyckliga argument (etiketter) på kommandoraden och gör något med vart och ett av dem.

I stället för att implementera `handle()` måste underklasser implementera `handle_label()`, som anropas en gång för varje etikett.

LabelCommand.label

  En sträng som beskriver de godtyckliga argument som skickas till kommandot. Strängen används i kommandots användningstext och felmeddelanden. Standardvärdet är `'label'`.

LabelCommand.handle_label(label, **options)

  Utför kommandots åtgärder för `label`, som kommer att vara den sträng som anges på kommandoraden.

### Undantag för kommandon

exception CommandError(returncode=1)

Undantagsklass som indikerar ett problem under utförandet av ett managementkommando.

Om detta undantag uppstår under exekveringen av ett managementkommando från en kommandoradskonsol, kommer det att fångas upp och omvandlas till ett snyggt utskrivet felmeddelande till lämplig utdataström (t.ex. `stderr`); därför är det bästa sättet att ange att något har gått fel under exekveringen av ett kommando att skapa detta undantag (med en vettig beskrivning av felet). Det accepterar det valfria argumentet `returncode` för att anpassa avslutningsstatusen för hanteringskommandot att avslutas med, med hjälp av `sys.exit()`.

Om ett managementkommando anropas från kod genom `call_command()`, är det upp till dig att fånga upp undantaget när det behövs.