Django Typer¶
Use static typing to define the CLI for your Django management commands with Typer. Optionally
use the provided TyperCommand
class that inherits from
BaseCommand. This class maps the Typer interface onto a class based interface that Django
developers will be familiar with. All of the BaseCommand functionality is inherited, so that
TyperCommand
can be a drop in replacement.
django-typer makes it easy to:
Define your command CLI interface in a clear, DRY and safe way using type hints
Create subcommands and hierarchical groups of commands.
Use the full power of Typer’s parameter types to validate and parse command line inputs.
Create beautiful and information dense help outputs.
Configure the rendering of exception stack traces using rich.
Install shell tab-completion support for bash, zsh, fish and powershell.
Create custom and portable shell tab-completions for your CLI parameters.
Port existing commands (
TyperCommand
is interface compatible with BaseCommand).Use either a Django-style class-based interface or the Typer-style interface to define commands.
Add plugins to upstream commands.
Warning
Imports from django_typer
have been deprecated and will be removed in 3.0! Imports
have moved to django_typer.management
:
# old way
from django_typer import TyperCommand, command, group, initialize, Typer
# new way!
from django_typer.management import TyperCommand, command, group, initialize, Typer
Installation
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]"
Optionally add
django_typer
to yourINSTALLED_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.
Note
This documentation shows all examples using both the function oriented Typer-style interface
and the class based Django-style interface in separate tabs. Each interface is functionally
equivalent so the choice of which to use is a matter of preference and familiarity. All
django-typer commands are instances of TyperCommand
,
including commands defined in the Typer-style interface. This means you may always specify a
self argument to receive the instance of the command in your functions.
Basic Example
TyperCommand
is a drop in extension to BaseCommand. All of the
documented features of BaseCommand work the same way! Or, you may also use an interface identical
to Typer’s. Simply import Typer from django_typer instead of typer.
1from django_typer.management 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 """
1from django_typer.management import Typer
2
3app = Typer()
4
5
6@app.command()
7def main(arg1: str, arg2: str, arg3: float = 0.5, arg4: int = 1):
8 """
9 A basic command that uses Typer
10 """
Multiple Subcommands Example
Commands with multiple subcommands can be defined:
1import typing as t
2
3from django.utils.translation import gettext_lazy as _
4from typer import Argument
5
6from django_typer.management 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[
18 str, Argument(help=_("The name of the object to create."))
19 ],
20 ):
21 """
22 Create an object.
23 """
24
25 @command()
26 def delete(
27 self,
28 id: t.Annotated[
29 int, Argument(help=_("The id of the object to delete."))
30 ],
31 ):
32 """
33 Delete an object.
34 """
1import typing as t
2
3from django.utils.translation import gettext_lazy as _
4from typer import Argument
5
6from django_typer.management import Typer
7
8app = Typer(help="A command that defines subcommands.")
9
10
11@app.command()
12def create(
13 name: t.Annotated[
14 str, Argument(help=_("The name of the object to create."))
15 ],
16):
17 """
18 Create an object.
19 """
20
21
22@app.command()
23def delete(
24 id: t.Annotated[int, Argument(help=_("The id of the object to delete."))],
25):
26 """
27 Delete an object.
28 """
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. The Typer-style interface builds a
TyperCommand
class for us that allows you to optionally accept
the self argument in your commands.
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.management import TyperCommand, group
8
9
10class Command(TyperCommand):
11 help = _("A more complex command that defines a hierarchy of subcommands.")
12
13 precision = 2
14
15 @group(help=_("Do some math at the given precision."))
16 def math(
17 self,
18 precision: t.Annotated[
19 int, Option(help=_("The number of decimal places to output."))
20 ] = precision,
21 ):
22 self.precision = precision
23
24 @math.command(help=_("Multiply the given numbers."))
25 def multiply(
26 self,
27 numbers: t.Annotated[
28 t.List[float], Argument(help=_("The numbers to multiply"))
29 ],
30 ):
31 return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
32
33 @math.command()
34 def divide(
35 self,
36 numerator: t.Annotated[float, Argument(help=_("The numerator"))],
37 denominator: t.Annotated[float, Argument(help=_("The denominator"))],
38 floor: t.Annotated[bool, Option(help=_("Use floor division"))] = False,
39 ):
40 """
41 Divide the given numbers.
42 """
43 if floor:
44 return str(numerator // denominator)
45 return f"{numerator / denominator:.{self.precision}f}"
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.management import Typer
8
9app = Typer(
10 help=_("A more complex command that defines a hierarchy of subcommands.")
11)
12
13
14math_grp = Typer(help=_("Do some math at the given precision."))
15
16app.add_typer(math_grp)
17
18
19@math_grp.callback()
20def math(
21 self,
22 precision: t.Annotated[
23 int, Option(help=_("The number of decimal places to output."))
24 ] = 2,
25):
26 self.precision = precision
27
28
29@math_grp.command(help=_("Multiply the given numbers."))
30def multiply(
31 self,
32 numbers: t.Annotated[
33 t.List[float], Argument(help=_("The numbers to multiply"))
34 ],
35):
36 return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
37
38
39@math_grp.command()
40def divide(
41 self,
42 numerator: t.Annotated[float, Argument(help=_("The numerator"))],
43 denominator: t.Annotated[float, Argument(help=_("The denominator"))],
44 floor: t.Annotated[bool, Option(help=_("Use floor division"))] = False,
45):
46 """
47 Divide the given numbers.
48 """
49 if floor:
50 return str(numerator // denominator)
51 return f"{numerator / denominator:.{self.precision}f}"
- Tutorial: Building Commands
- Tutorial: Inheritance & Plugins
- Tutorial: Shell Tab-Completions
- How-To
- Define an Argument
- Define an Option
- Define Multiple Subcommands
- Define Multiple Subcommands w/ a Default
- Define Groups of Commands
- Define an Initialization Callback
- Call Commands from Code
- Change Default Django Options
- Configure Typer Options
- Define Shell Tab Completions for Parameters
- Debug Shell Tab Completers
- Inherit/Override Commands
- Plugin to Existing Commands
- Configure rich Stack Traces
- Add Help Text to Commands
- Order Commands in Help Text
- Document Commands w/Sphinx
- print, self.stdout and typer.echo
- Reference
- Change Log
- v2.6.0 (2024-12-03)
- v2.5.0 (2024-11-29)
- v2.4.0 (2024-11-07)
- v2.3.0 (2024-10-13)
- v2.2.2 (2024-08-25)
- v2.2.1 (2024-08-17)
- v2.2.0 (2024-07-26)
- v2.1.3 (2024-07-15)
- v2.1.2 (2024-06-07)
- v2.1.1 (2024-06-06)
- v2.1.0 (2024-06-05)
- v2.0.2 (2024-06-03)
- v2.0.1 (2024-05-31)
- v2.0.0 (2024-05-31)
- v1.1.2 (2024-04-22)
- v1.1.1 (2024-04-11)
- v1.1.0 (2024-04-03)
- v1.0.9 (yanked)
- v1.0.8 (2024-03-26)
- v1.0.7 (2024-03-17)
- v1.0.6 (2024-03-14)
- v1.0.5 (2024-03-14)
- v1.0.4 (2024-03-13)
- v1.0.3 (2024-03-08)
- v1.0.2 (2024-03-05)
- v1.0.1 (2024-02-29)
- v1.0.0 (2024-02-26)
- v0.6.1b (2024-02-24)
- v0.6.0b (2024-02-23)
- v0.5.0b (2024-01-31)
- v0.4.0b (2024-01-08)
- v0.3.0b (2024-01-06)
- v0.2.0b (2024-01-04)
- v0.1.0b (2023-12-05)