Nested management commands in Django

440 Views Asked by At

Is there anyway to create nested management commands in Django, similar to what the docker and kubectl have? For example, let's say I need to have the following structure:

|-->manage.py
    |-->restaurant
        |-->list
        |-->get
    |-->employee
        |-->list
        |-->get
        |-->delete

The following commands should all be possible:

./manage.py -h
./manage.py restaurant -h
./manage.py restaurant list
./manage.py employee list
./manage.py restaurant get ""
./manage.py employee delete tiffany

The argparse subparser looks promising but I feel like there should be an easier way using python modules in the app/management/commands or something like that.

2

There are 2 best solutions below

0
On

You can add an argument for that.

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

class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument('command_type', type=str)

    def handle(self, *args, **options):
        command_type = options['command_type']
        if command_type == 'list':
            # list command
            return
        elif command_type == 'get':
            # get command
            return
        raise CommandError('Invalid arguemnt for command_type')

Usage:

py manage.py my_command get
py manage.py my_command list
1
On

django-typer does not separate the subcommands into different modules like in your example, but it does use the power of click/typer to make it super easy to define arbitrarily complex command trees:

import typing as t

from django.utils.translation import gettext_lazy as _
from typer import Argument

from django_typer import TyperCommand, command


class Command(TyperCommand):
   """
   A command that defines subcommands.
   """

   @command()
   def create(
      self,
      name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
   ):
      """
      Create an object.
      """

   @command()
   def delete(
      self, id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]
   ):
      """
      Delete an object.
      """