Johnny Metz
Johnny Metz

Reputation: 5965

Nested management commands in Django

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.

Upvotes: 2

Views: 555

Answers (2)

bckohan
bckohan

Reputation: 243

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.
      """

Upvotes: 0

Felix Eklöf
Felix Eklöf

Reputation: 3720

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

Upvotes: 0

Related Questions