Reputation: 41
I want to implement django app namespacing in commands like
python manage.py appname:command --parameters
and
python manage.py appname:command:subcommand --parameters
how I can do this ?
Upvotes: 4
Views: 441
Reputation: 6555
Django management commands are based on argparse (since Django 1.10 [1]) from the Python standard library. One possible solution is to use subparser. [2]
First create a file as a standard management command, e.g.: yourapp/management/commands/base.py
.
from __future__ import annotations
from typing import Any, Callable, Dict
from django.core.management.base import BaseCommand
def create_resource(**options):
print("Creating resource %s" % options["name_of_resource_to_create"])
def delete_resource(**options):
print("Deleting resource %s" % options["name_of_resource_to_delete"])
SUBCOMMANDS_MAPPING: Dict[str, Callable[[Dict[str, Any]], None]] = {
"create_resource": create_resource,
"delete_resource": delete_resource,
}
class Command(BaseCommand):
def add_arguments(self, parser):
subparsers = parser.add_subparsers(
dest="subcommand",
title="positional arguments:",
description="Required positional arguments to specify subcommand to execute.",
required=True,
)
# Parser for create_resource:
parser_serve = subparsers.add_parser(name="create_resource")
parser_serve.add_argument("name_of_resource_to_create", type=str)
# Parser for delete_resource:
parser_serve = subparsers.add_parser(name="delete_resource")
parser_serve.add_argument("name_of_resource_to_delete", type=str)
def handle(self, *args, **options):
print('Base command')
SUBCOMMANDS_MAPPING[options.pop("subcommand")](**options)
We added a subparser called subcommand
. Each subcommand has its own separate required/optional arguments. The subcommand name will be contained in the subcommand
key. Based on this value, we decide which function to run.
This is what the help output looks like:
$ python manage.py base --help
usage: manage.py base [-h] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--force-color] [--skip-checks] {create_resource,delete_resource} ...
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, e.g. "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, e.g. "/home/djangoprojects/myproject".
--traceback Raise on CommandError exceptions
--no-color Don't colorize the command output.
--force-color Force colorization of the command output.
--skip-checks Skip system checks.
positional arguments::
Required positional arguments to specify subcommand to execute.
{create_resource,delete_resource}
$ python manage.py create_resource --help
usage: manage.py base create_resource [-h] name_of_resource_to_create
positional arguments:
name_of_resource_to_create
optional arguments:
-h, --help show this help message and exit
I tested this solution in Django 3.1 and Python 3.9. The source of inspiration for me was this answer: https://stackoverflow.com/a/37414551/752142.
Upvotes: 1