Création de commandes de gestion dans Django

Commandes de gestion - commandes exécutées à partir de la ligne de commande à l'aide du script manage.py.

Les domaines d'application les plus courants sont les actions qui sont effectuées une fois ou périodiquement, mais pour lesquelles le lancement via le planificateur n'est pas disponible pour une raison quelconque. Par exemple, envoyer des messages ponctuels aux utilisateurs, récupérer des données d'une base de données, vérifier la présence des fichiers et dossiers nécessaires avant de lancer les mises à jour, créer rapidement des objets de modèle pendant le développement, etc.

Les bases


Les commandes sont créées dans les répertoires des applications (les applications doivent être ajoutées à INSTALED_APPS), dans le sous-répertoire app / management / commandes. Un fichier distinct est créé pour chaque commande. Les fichiers seront disponibles à partir de la ligne de commande, à l'exception de ceux qui commencent par un trait de soulignement.

app/ __init__.py management/ __init__.py commands/ __init__.py _tools.py zen.py 

Dans cet exemple, la commande zen sera disponible, mais pas _tools.

Les commandes sont créées en héritant de la classe django.core.management.base.BaseCommand. Dans le cas le plus simple, il suffit de réécrire la fonction handle. Cette commande sera exécutée et le résultat renvoyé par elle sera imprimé dans la console.

 from django.core.management.base import BaseCommand class Command(BaseCommand): help = 'The Zen of Python' def handle(self, *args, **options): import this 

Essayons d'appeler notre commande:

 python manage.py zen The Zen of Python, by Tim Peters Beautiful is better than ugly. ... 

L'attribut de la classe d'aide est une description qui s'affiche lorsqu'une commande avec le commutateur --help est appelée ou si la commande n'est pas entrée correctement.

 $ python manage.py zen --help usage: manage.py zen [-h] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] The Zen of Python optional arguments: -h, --help show this help message and exit --version show program's version number and exit -v {0,1,2,3}, --verbosity {0,1,2,3} Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output --settings SETTINGS The Python path to a settings module, eg "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used. --pythonpath PYTHONPATH A directory to add to the Python path, eg "/home/djangoprojects/myproject". --traceback Raise on CommandError exceptions --no-color Don't colorize the command output. 

Analyse des arguments


Comme nous pouvons le voir, notre équipe prend déjà 7 arguments.

Mais que se passe-t-il si cela ne nous suffit pas et que nous voulons ajouter nos propres options? Pour ce faire, vous devez créer la fonction add_arguments dans notre classe, où répertorier tous les arguments que nous voulons transmettre à notre équipe. Chaque argument est créé en appelant la fonction parser.add_argument avec une série de paramètres.

Supposons que nous ne soyons pas à l'aise avec la sortie longue de notre fonction, et que nous voulons que Hello world soit imprimé avec les touches -s et --short:

 from django.core.management.base import BaseCommand class Command(BaseCommand): help = 'The Zen of Python' def handle(self, *args, **options): if options['short']: import __hello__ else: import this def add_arguments(self, parser): parser.add_argument( '-s', '--short', action='store_true', default=False, help='  ' ) 

Ce fichier imprimera Hello world lorsqu'il est appelé avec le commutateur -s.

 $ python manage.py zen -s Hello world... (coolwriter)$ python manage.py zen The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. ... 

Examinons plus en détail la façon dont l'analyse des arguments est spécifiée.

L'analyseur est hérité de argparse.ArgumentParser et vous pouvez lire les arguments pris par la fonction add_argument dans la documentation de la bibliothèque argparse dans la documentation python. Les plus importants sont:

nom ou drapeaux - nom ou liste de noms et d'étiquettes. Nous avons ce «court», «-s» et «- court».
action - que faire de la valeur de l'argument. Les options les plus intéressantes (mais pas toutes) sont les suivantes:

store - enregistrez comme valeur de notre option. Si plusieurs paires clé-valeur sont transmises, la valeur de la dernière
store_const - enregistre la valeur constante dans la clé de nom. La constante est passée comme argument const à la même fonction add_argument.

Par exemple:

 parser.add_argument('my_option', action='store_const', const=1234) 

La fonction de poignée dans les options sera passée 'my_option': 1234

store_true, store_false - cas particuliers de l'option précédente. Vrai ou faux stocké
append - la valeur sera ajoutée à la fin de la liste
append_const est le même que le précédent, mais la valeur passée à l'argument const ajoute (qui peut être n'importe quel objet)

nargs est le nombre d'arguments. Valeurs possibles: entier, '?' - un ou la valeur par défaut de l'argument par défaut, '*' - autant qu'il y en a, et sont collectés dans une liste, '+' - au moins un, et si plusieurs - sont collectés dans une liste, argparse.REMAINDER - tous les arguments restants de la ligne de commande y sont collectés . Incompatible avec action = const

Remarque: si vous utilisez cet argument, la valeur de votre option dans la ligne de commande sera transmise pour être gérée comme une liste, même s'il n'y a qu'un seul élément. (Dans ce cas, la valeur par défaut est transmise telle quelle, sans transtypage dans la liste.)

par défaut est la valeur par défaut .
type - transtypez l'argument dans le type spécifié.
choix - restriction des variantes de la valeur de l'argument. La valeur de choix est passée une liste de valeurs possibles
required est un argument requis.
help - Une description de ce que fait cet argument.
dest - si vous souhaitez enregistrer votre option sous un nom différent, vous pouvez spécifier dest = 'my_new_name'. Sinon, le nom de l'argument sera utilisé.
Ces arguments seront ensuite passés à la fonction handle en tant que dictionnaire d'options.

Mais que faire si nous voulons passer des arguments sans nom à gérer?

Dans ce cas, vous devez spécifier dans add_arguments la réception de tous les arguments sans nom dans l'option args. Par exemple, si nous voulons passer plusieurs entiers à la commande:

 def add_arguments(self, parser): parser.add_argument( nargs='+', type=int, dest = 'args' ) 

Ordre d'exécution


La commande est exécutée dans l'ordre suivant:

  1. Tout d'abord, la méthode run_from_argv () est appelée. Cette méthode crée un analyseur par le biais d'un appel à create_parser, et l'analyseur créé ajoute des arguments par défaut (de type no-color), et appelle également la méthode add_arguments, ajoutant ainsi toutes les options que nous avons créées.
  2. Après cela, la fonction d'exécution est appelée. Cette fonction effectue plusieurs vérifications, puis exécute la fonction handle. Le résultat de la poignée est imprimé sur la sortie standard.

Bien sûr, chacune de ces fonctions peut être personnalisée. Par exemple, dessinons la belle sortie d'un message d'aide multiligne:

 from argparse import RawTextHelpFormatter def create_parser(self, prog_name, subcommand): parser = super(Command, self).create_parser(prog_name, subcommand) parser.formatter_class = RawTextHelpFormatter return parser 

C'est probablement tout ce qui est nécessaire pour écrire des commandes de gestion dans la plupart des cas.

Conclusion


L'article ne prétend pas être un aperçu complet de toutes les possibilités lors de la création de commandes de gestion - elles sont décrites dans la documentation Django. Les personnes intéressées peuvent se tourner vers
documentation .

L'analyse des arguments de ligne de commande là-bas, hélas, n'est pratiquement pas divulguée. Ceux qui souhaitent se plonger dans les subtilités de cette question devraient étudier le cumul de python.

Module Argparse

Source: https://habr.com/ru/post/fr415049/


All Articles