Django Typer

Use Typer to define the CLI for your Django management commands. Provides a TyperCommand class that inherits from BaseCommand and allows typer-style annotated parameter types. All of the BaseCommand functionality is preserved, so that TyperCommand can be a drop in replacement.

django-typer makes it easy to:

Installation

  1. Clone django-typer from GitHub or install a release off PyPI :

    pip install django-typer
    

    rich is a powerful library for rich text and beautiful formatting in the terminal. It is not required, but highly recommended for the best experience:

    pip install "django-typer[rich]"
    
  2. Add django_typer to your INSTALLED_APPS setting:

    INSTALLED_APPS = [
        ...
        'django_typer',
    ]
    

    You only need to install django_typer as an app if you want to use the shellcompletion command to enable tab-completion or if you would like django-typer to install rich traceback rendering for you - which it does by default if rich is also installed.

Basic Example

For example TyperCommands can be a very simple drop in replacement for BaseCommands. All of the documented features of BaseCommand work!

A Basic Command
1from django_typer import TyperCommand
2
3
4class Command(TyperCommand):
5    def handle(self, arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):
6        """
7        A basic command that uses Typer
8        """
./manage.py basic Usage: ./manage.py basic [OPTIONS] ARG1 ARG2 A basic command that uses Typer ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ *arg1TEXT[default: None][required] *arg2TEXT[default: None][required] ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --arg3FLOAT  [default: 0.5] --arg4INTEGER[default: 1] --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Django ─────────────────────────────────────────────────────────────────────╮ --versionShow program's version number and exit. --settingsTEXTThe 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.                            --pythonpathPATHA directory to add to the Python path, e.g.       "/home/djangoprojects/myproject".                 [default: None]                                   --tracebackRaise on CommandError exceptions --no-colorDon't colorize the command output. --force-colorForce colorization of the command output. --skip-checksSkip system checks. ╰──────────────────────────────────────────────────────────────────────────────╯

Multiple Subcommands Example

Or commands with multiple subcommands can be defined:

A Command w/Subcommands
 1import typing as t
 2
 3from django.utils.translation import gettext_lazy as _
 4from typer import Argument
 5
 6from django_typer import TyperCommand, command
 7
 8
 9class Command(TyperCommand):
10    """
11    A command that defines subcommands.
12    """
13
14    @command()
15    def create(
16        self,
17        name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
18    ):
19        """
20        Create an object.
21        """
22
23    @command()
24    def delete(
25        self, id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]
26    ):
27        """
28        Delete an object.
29        """
./manage.py multi Usage: ./manage.py multi [OPTIONS] COMMAND [ARGS]... ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Django ─────────────────────────────────────────────────────────────────────╮ --versionShow program's version number and exit. --settingsTEXTThe 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.                            --pythonpathPATHA directory to add to the Python path, e.g.       "/home/djangoprojects/myproject".                 [default: None]                                   --tracebackRaise on CommandError exceptions --no-colorDon't colorize the command output. --force-colorForce colorization of the command output. --skip-checksSkip system checks. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ create Create an object.                                                   delete Delete an object.                                                   ╰──────────────────────────────────────────────────────────────────────────────╯
./manage.py multi create Usage: ./manage.py multi create [OPTIONS] NAME Create an object. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ *nameTEXTThe name of the object to create.[default: None] [required]                        ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯
./manage.py multi delete Usage: ./manage.py multi delete [OPTIONS] ID Delete an object. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ *idINTEGERThe id of the object to delete.[default: None] [required]                      ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯

Grouping and Hierarchies Example

Or more complex groups and subcommand hierarchies can be defined. For example this command defines a group of commands called math, with subcommands divide and multiply. The group has a common initializer that optionally sets a float precision value. We would invoke this command like so:

./manage.py hierarchy math --precision 5 divide 10 2.1
4.76190
./manage.py hierarchy math multiply 10 2
20.00

Any number of groups and subcommands and subgroups of other groups can be defined allowing for arbitrarily complex command hierarchies.

A Command w/Grouping Hierarchy
 1import typing as t
 2from functools import reduce
 3
 4from django.utils.translation import gettext_lazy as _
 5from typer import Argument, Option
 6
 7from django_typer import TyperCommand, group
 8
 9
10class Command(TyperCommand):
11
12    help = _("A more complex command that defines a hierarchy of subcommands.")
13
14    precision = 2
15
16    @group(help=_("Do some math at the given precision."))
17    def math(
18        self,
19        precision: t.Annotated[
20            int, Option(help=_("The number of decimal places to output."))
21        ] = precision,
22    ):
23        self.precision = precision
24
25    @math.command(help=_("Multiply the given numbers."))
26    def multiply(
27        self,
28        numbers: t.Annotated[
29            t.List[float], Argument(help=_("The numbers to multiply"))
30        ],
31    ):
32        return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
33
34    @math.command()
35    def divide(
36        self,
37        numerator: t.Annotated[float, Argument(help=_("The numerator"))],
38        denominator: t.Annotated[float, Argument(help=_("The denominator"))],
39        floor: t.Annotated[bool, Option(help=_("Use floor division"))] = False,
40    ):
41        """
42        Divide the given numbers.
43        """
44        if floor:
45            return str(numerator // denominator)
46        return f"{numerator / denominator:.{self.precision}f}"
./manage.py hierarchy Usage: ./manage.py hierarchy [OPTIONS] COMMAND [ARGS]... A more complex command that defines a hierarchy of subcommands. ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Django ─────────────────────────────────────────────────────────────────────╮ --versionShow program's version number and exit. --settingsTEXTThe 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.                            --pythonpathPATHA directory to add to the Python path, e.g.       "/home/djangoprojects/myproject".                 [default: None]                                   --tracebackRaise on CommandError exceptions --no-colorDon't colorize the command output. --force-colorForce colorization of the command output. --skip-checksSkip system checks. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ math Do some math at the given precision.                                  ╰──────────────────────────────────────────────────────────────────────────────╯
./manage.py hierarchy math Usage: ./manage.py hierarchy math [OPTIONS] COMMAND [ARGS]... Do some math at the given precision. ╭─ Options ────────────────────────────────────────────────────────────────────╮ --precisionINTEGERThe number of decimal places to output. [default: 2]                            --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ divide   Divide the given numbers.                                         multiply Multiply the given numbers.                                       ╰──────────────────────────────────────────────────────────────────────────────╯
./manage.py hierarchy math divide Usage: ./manage.py hierarchy math divide [OPTIONS] NUMERATOR DENOMINATOR Divide the given numbers. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ *numerator  FLOATThe numerator[default: None][required] *denominatorFLOATThe denominator[default: None][required] ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --floor--no-floorUse floor division[default: no-floor] --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯
./manage.py hierarchy math multiply Usage: ./manage.py hierarchy math multiply [OPTIONS] NUMBERS... Multiply the given numbers. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ *numbersNUMBERS...The numbers to multiply[default: None] [required]              ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯