django-admin
personalizzati¶Le applicazioni possono registrare le proprie azioni con manage.py
. Per esempio, potresti voler aggiungere una azione manage.py
per una applicazione Django che stai distribuendo. In questo documento, costruiremo un comando personalizzato closepoll
per l’applicazione polls
dal tutorial.
Per fare questo, aggiungi una directory management/commands
all’applicazione. Django registrerà un comando manage.py
per ogni modulo Python in quella directory il cui nome non inizi con un underscore. Per esempio:
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py
In questo esempio, il comando closepoll
sarà reso disponibile a qualsiasi progetto che includa l’applicazione polls
in INSTALLED_APPS
.
Il modulo _private.py
non sarà disponibile come comando di management.
Il modulo closepoll.py
ha un solo requisito – deve definire una classe Command
che estenda BaseCommand
o una delle sue sottoclassi.
Script standalone
Il comandi di management personalizzati sono utili soprattutto per lanciare script standalone o per script che sono eseguiti periodicamente con il crontab di UNIX o dal pannello di controllo per la pianificazione dei task di Windows.
Per implementare il comando, modifica polls/management/commands/closepoll.py
in questo modo :
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))
Nota
Quando utilizzi i comandi di management personalizzati e vuoi ottenere dell’output su console, dovresti scrivere su self.stdout
e self.stderr
, invece che direttamente su stdout` and stderr
. Utilizzando questi proxy, diventa molto più facile testare il tuo comando personalizzato. Nota anache che non hai bisogno di terminare i messaggi con il carattere di newline, sarà aggiunto automaticamente, a meno che tu non specifichi il parametro ending
:
self.stdout.write("Unterminated line", ending='')
Il nuovo comando personalizzato potrà essere chiamato con python manage.py closepoll <poll_ids>
.
Il metodo handle()
prende uno o più poll_ids
ed imposta poll.opened
a False
per ognuno di essi. Se l’utente fa riferimento ad un poll non esistente, viene sollevato un CommandError
. L’attributo poll.opened
non esiste nel tutorial ed è stato aggiunto a polls.models.Question
per questo esempio.
Lo stesso closepoll
può essere modificato facilmente per cancellare un dato poll invece che chiuderlo accettando opzioni sulla command line. Queste opzioni personalizzate possono essere aggiunte nel metodo add_arguments()
così:
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()
# ...
L’opzione (delete
nel nostro esempio) è disponibile nel dizionario di parametri delle opzioni del metodo handle. Vedi la documentazione di Python di argparse
per saperne di più sull’utilizzo di add_argument
.
Oltre ad essere in grado di aggiungere opzioni personalizzate per la command line, tutti i comandi di management possono accettare alcune opzioni di default come --verbosity
e --traceback
.
Di default, i comandi di management sono eseguiti con il locale che è correntemente attivo.
Se, per qualche ragione, il tuo comando di management personalizzato deve girare senza un locale attivo (per esempio, per evitare che il contenuto tradotto venga inserito nel database), disattiva le traduzioni usando il decoratore @no_translations
sul tuo metodo handle()
from django.core.management.base import BaseCommand, no_translations
class Command(BaseCommand):
...
@no_translations
def handle(self, *args, **options):
...
Dal momento che la disattivazione della traduzione richiede l’accesso alle impostazioni di configurazione, il decoratore non può essere usato per comandi che funzionino senza impostazioni di configurazione.
Informazioni su come testare i comandi di management personalizzati possono essere trovate nei documenti di testing.
Django registra i comandi built-in e poi cerca comandi in INSTALLED_APPS
in senso inverso. Durante la ricerca, se un nome di comando duplica un comando già registrato, fa override su quello precedente.
In altre parole, per fare override di un comando, il nuovo comando deve avere lo stesso nome e la sua app deve trovarsi prima di quella del comando su cui fare override in INSTALLED_APPS
.
I comandi di management di app di terze parti che sono stati sovrascritti in modo non intenzionale posso essere resi disponibili con un nuovo nome creando un nuovo comando in una delle app del tuo progetto (che si trovi in ordine prima dell’app di terze parti in INSTALLED_APPS
) che importi il Command
del comando sovrascritto.
BaseCommand
¶La classe di base da cui, in ultima analisi, tutti i comandi di management derivano.
Usa questa classe se vuoi accedere a tutti i meccanismi che fanno parsing degli argomenti di command-line e cercano di capire quale codice chiamare in risposta; se non hai bisogno di cambiare questo comportamento, considera di usare una delle sue sottoclassi.
Fare una sottoclasse della classe BaseCommand
ti richiede di implementare il metodo handle()
.
Tutti gli attributi possono essere impostati nella tua classe derivata e possono essere usati nelle sottoclassi di BaseCommand
.
BaseCommand.
help
¶Una breve descrizione del comando, che sarà stampata nel messaggio di aiuto quando l’utente lancia il comando python manage.py help <command>
.
BaseCommand.
missing_args_message
¶Se il tuo comando definisce degli argomenti posizionali obbligatori, puoi personalizzare il messaggio di errore restituito in caso di argomenti mancanti. Quello di default è restituito da argparse
(«too few arguments»).
BaseCommand.
output_transaction
¶Un booleano che indica se il comando mostra in output uno statement SQL; se True
, l’output sarà automaticamente inserito tra BEGIN;
e COMMIT;
. Il valore predefinito è False
.
BaseCommand.
requires_migrations_checks
¶Un booleano; se True
, il comando stampa un messaggio di warning se il set di migrazioni su disco non corrisponde a quelle sul database. Un warning non impedisce l’esecuzione del comando. Il valore predefinito è False
.
BaseCommand.
requires_system_checks
¶Un lista di tuple di tag, per esempio [Tags.staticfiles, Tags.models]
. Il sistema controlla che la registrazione nei tag scelti sia sottoposta a controllo di errori prima di eseguire il comando. Il valore '__all__'
può essere usato per specificare che tutti i controlli siano eseguiti. Il valore predefinito è '__all__'
.
BaseCommand.
style
¶Un attributo di istanza che aiuta a creare output colorato quando si scrive su stdout
o stderr
. Per esempio:
self.stdout.write(self.style.SUCCESS('...'))
Vedi Syntax coloring per imparare come modificare la palette di colori e visualizzare gli stili disponibili (usa le versioni maiuscole dei «ruoli» descritti in quella sezione).
Se passi l’opzione --no-color
quando lanci il comando, tutte le chiamate self.style()
restituiranno la stringa originale senza colori.
BaseCommand.
suppressed_base_arguments
¶Le opzioni dei comandi di default da sopprimere nell’output dell’help. Dovrebbe essere un set di nomi di opzione (per es. '--verbosity'
). I valori di default per tutte le opzioni soppresse vengono comunque passati.
La classe BaseCommand
ha pochi metodi che possono essere sovrascritti ma solo il metodo handle()
deve essere implementato.
Implementazione di un constructor in una subclasse
Se implementi __init__
nella tua sottoclasse di BaseCommand
, devi chiamare __init__
di BaseCommand
:
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# ...
BaseCommand.
create_parser
(prog_name, subcommand, **kwargs)¶Restituisce una istanza di CommandParser
, che è una sottoclasse di ArgumentParser
con qualche personalizzazione per Django.
Puoi personalizzare l’istanza sovrascrivendo questo metodo e chiamando super()
con parametri kwargs
ArgumentParser
.
BaseCommand.
add_arguments
(parser)¶L’entry point per aggiungere argomenti del parser per gestire gli argomenti della command line passati al comando. I comandi personalizzati dovrebbero sovrascrivere questo metodo per aggiungere sia argomenti facoltativi che posizionali che siano accettati dal comando. Non è necessario chiamare super()
quando si utilizza una sottoclasse di BaseCommand
.
BaseCommand.
get_version
()¶Restituisce la versione di Django, che dovrebbe essere corretta per tutti i comandi Django built-in. I comandi forniti dall’utente possono sovrascrivere questo metodo per restituire la propria versione.
BaseCommand.
execute
(*args, **options)¶Cerca di eseguire questo comando, facendo i controlli di sistema se necessario (come controllato con l’attributo requires_system_checks
). Se il comando solleva CommandError
, questo viene intercettato e stampato su stderr
.
Chiamata di un commando di ?gestione? nel tuo codice
execute()` non dovrebbe essere chiamato direttamente dal tuo codice per eseguire un comando. Usa invece call_command()
.
BaseCommand.
handle
(*args, **options)¶La logica attuale del comando. Le sottoclassi devono implementare questo metodo
Può restituire una stringa che sarà stampata su stdout
(tra BEGIN;
e COMMIT;
se output_transaction
è True
).
BaseCommand.
check
(app_configs=None, tags=None, display_num_errors=False)¶Usa il framework di controlli di sistema per ispezionare l’intero progetto Django in cerca di potenziali problemi. I problemi gravi sono segnalati cpme CommandError
; i warning sono stampati su stderr
; le notifiche minori sono stampate su stdout
.
Se app_configs
e tags
sono entrambi None
, sono effettuati tutti i controlli di sistema. tags
può essere una lista di tag di controllo, come compatibility
o models
.
BaseCommand
¶AppCommand
¶Un comando di gestione che accetta una o più etichette di applicazioni installate come argomenti e fa qualcosa con ciascuna di esse.
Piuttosto che implementare handle()
, le sottoclassi devono implementare handle_app_config()
, che sarà chiamata una volta per ogni applicazione.
AppCommand.
handle_app_config
(app_config, **options)¶Effettua le azioni del comando per app_config
, che sarà una istanza di AppConfig
corrispondente ad una etichetta di applicazione fornita sulla linea di comando.
LabelCommand
¶Un comando di gestione che accetta uno o più argomenti arbitrari (etichette) dalla linea di comando e fa qualcosa con ciascuno di essi.
Piuttosto che implementare handle()
, le sottoclassi devono implmentare handle_label()
, che sarà chiamato una volta per ogni etichetta.
LabelCommand.
label
¶Una stringa che descrive gli argomenti arbitrari forniti al comando. La stringa viene usata nel testo di utilizzo e nei messaggi di errore del comando. Di default è pari a 'label'
.
LabelCommand.
handle_label
(label, **options)¶Effettua le azioni del comando per label
, che sarà la stringa come è fornita dalla riga di comando.
CommandError
(returncode=1)¶Una classe di eccezione che indica un problema mentre si esegue un comando di gestione.
Se questa eccezione viene sollevata durante l’esecuzione di un comando di management da una console a linea di comando, sarà gestito e trasformato in un messaggio di errore stampato in modo gradevole verso lo stream di output appropriato (per es. stderr
); di conseguenza, sollevare questa eccezione (con una descrizione sensibile dell’errore) è la modalità preferita di indicare che qualcosa è andato storto durante l’esecuzione di un comando. Essa accetta l’argomento opzionale returncode
per personalizzare l’exit status del comando di management, usando sys.exit()
.
Se il comando di gestione è chiamato dal codice con call_command()
, è tuo compito catturare l’eccezione quando è necessario.
mar 08, 2023