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 options dict-parametern i handle-metoden. Se Python-dokumentationen för argparse
för mer information om hur add_argument
används.
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¶
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 positionella argument kan du anpassa det felmeddelande som returneras om argument saknas. Standardvärdet är det som matas ut 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 avBEGIN;
ochCOMMIT;
. Standardvärdet ärFalse
.
- 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 ärFalse
.
- BaseCommand.requires_system_checks¶
En lista eller tupel av taggar, t.ex.
[Tags.staticfiles, Tags.models]
. Systemkontroller :ref:registrerade i de valda taggarna <registering-labeling-checks>
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
ellerstderr
. 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 avself.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)[source]¶
Returnerar en
CommandParser
-instans, som är enArgumentParser
-underklass med några anpassningar för Django.Du kan anpassa instansen genom att åsidosätta den här metoden och anropa
super()
medkwargs
avArgumentParser
-parametrar.
- BaseCommand.add_arguments(parser)[source]¶
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 avBaseCommand
.
- BaseCommand.get_version()[source]¶
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)[source]¶
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 ettCommandError
, fångas det upp och skrivs ut tillstderr
.
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)[source]¶
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 avBEGIN;
ochCOMMIT;
omoutput_transaction
ärTrue
).
- BaseCommand.check(app_configs=None, tags=None, display_num_errors=False, include_deployment_checks=False, fail_level=checks.ERROR, databases=None)[source]¶
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 tillstderr
; mindre meddelanden skickas ut tillstdout
.Om
app_configs
ochtags
båda ärNone
utförs alla systemkontroller utom distributions- och databasrelaterade kontroller.tags
kan vara en lista med kontrolltaggar, t.ex.compatibility
ellermodels
.Du kan ange
include_deployment_checks=True
för att även utföra deployment-kontroller och en lista med databasalias idatabases
för att köra databasrelaterade kontroller mot dem.
- BaseCommand.get_check_kwargs(options)[source]¶
- New in Django 5.2.
Tillhandahåller kwargs för anropet till
check()
, inklusive omvandling av värdet avrequires_system_checks
till kwargtag
.Å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ättaget_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 enAppConfig
-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¶
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.