Reference

django_typer

    ___ _                           _____                       
   /   (_) __ _ _ __   __ _  ___   /__   \_   _ _ __   ___ _ __ 
  / /\ / |/ _` | '_ \ / _` |/ _ \    / /\/ | | | '_ \ / _ \ '__|
 / /_//| | (_| | | | | (_| | (_) |  / /  | |_| | |_) |  __/ |   
/___,'_/ |\__,_|_| |_|\__, |\___/   \/    \__, | .__/ \___|_|   
     |__/             |___/               |___/|_|              

django-typer provides an extension class, TyperCommand, to the BaseCommand class that melds the Typer/click infrastructure with the Django infrastructure. The result is all the ease of specifying commands, groups and options and arguments using Typer and click in a way that feels like and is interface compatible with Django’s BaseCommand This should enable a smooth transition for existing Django commands and an intuitive feel for implementing new commands.

django-typer also supports shell completion for bash, zsh, fish and powershell and extends that support to native Django management commands as well.

The goal of django-typer is to provide full Typer style functionality while maintaining compatibility with the Django management command system. This means that the BaseCommand interface is preserved and the Typer interface is added on top of it. This means that this code base is more robust to changes in the Django management command system - because most of the base class functionality is preserved but many Typer and click internals are used directly to achieve this. We rely on robust CI to catch breaking changes upstream.

django_typer.command(name: str | None = None, *, cls: ~typing.Type[~django_typer.TyperCommandWrapper] = <class 'django_typer.TyperCommandWrapper'>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = None, help: str | None = None, epilog: str | None = None, short_help: str | None = None, options_metavar: str = '[OPTIONS]', add_help_option: bool = True, no_args_is_help: bool = False, hidden: bool = False, deprecated: bool = False, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, **kwargs: ~typing.Dict[str, ~typing.Any]) Callable[[Callable[[P], R]], Callable[[P], R]]

A function decorator that creates a new command and attaches it to the root command group. This is a passthrough to Typer.command() and the options are the same, except we swap the default command class for our wrapper.

We do not need to decorate handle() functions with this decorator, but if we want to pass options upstream to typer we can:

class Command(TyperCommand):

    @command(epilog="This is the epilog for the command.")
    def handle(self):
        ...

We can also use the command decorator to define multiple subcommands:

class Command(TyperCommand):

    @command()
    def command1(self):
        # execute command1 logic here

    @command(name='command2')
    def other_command(self):
        # arguments passed to the decorator are passed to typer and control
        # various aspects of the command, for instance here we've changed the
        # name of the command to 'command2' from 'other_command'

The decorated function is the command function. It may also be invoked directly as a method from an instance of the TyperCommand class, see get_command().

Parameters:
  • name – the name of the command (defaults to the name of the decorated function)

  • cls – the command class to use

  • context_settings – the context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need the help to be translated you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • no_args_is_help – whether to show the help if no arguments are provided

  • hidden – whether to hide the command from help output

  • deprecated – show a deprecation warning

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

django_typer.get_command(command_name: str, *subcommand: str, stdout: IO[str] | None = None, stderr: IO[str] | None = None, no_color: bool = False, force_color: bool = False) BaseCommand | MethodType

Get a Django command by its name and instantiate it with the provided options. This will work for subclasses of BaseCommand as well as for TyperCommand subclasses. If subcommands are listed for a TyperCommand, the method that corresponds to the command name will be returned. This method may then be invoked directly. If no subcommands are listed the command instance will be returned.

Using get_command to fetch a command instance and then invoking the instance as a callable is the preferred way to execute TyperCommand commands from code. The arguments and options passed to the __call__ method of the command should be fully resolved to their expected parameter types before being passed to the command. The call_command interface also works, but arguments must be unparsed strings and options may be either strings or resolved parameter types. The following is more efficient than call_command.

basic = get_command('basic')
result = basic(
    arg1,
    arg2,
    arg3=0.5,
    arg4=1
)

Subcommands may be retrieved by passing the subcommand names as additional arguments:

divide = get_command('hierarchy', 'math', 'divide')
result = divide(10, 2)
Parameters:
  • command_name – the name of the command to get

  • subcommand – the subcommand to get if any

  • stdout – the stdout stream to use

  • stderr – the stderr stream to use

  • no_color – whether to disable color

  • force_color – whether to force color

Raises:
  • ModuleNotFoundError – if the command is not found

  • LookupError – if the subcommand is not found

django_typer.group(name: str | None = <typer.models.DefaultPlaceholder object>, cls: ~typing.Type[~django_typer.TyperGroupWrapper] = <class 'django_typer.TyperGroupWrapper'>, invoke_without_command: bool = <typer.models.DefaultPlaceholder object>, no_args_is_help: bool = <typer.models.DefaultPlaceholder object>, subcommand_metavar: str | None = <typer.models.DefaultPlaceholder object>, chain: bool = <typer.models.DefaultPlaceholder object>, result_callback: ~typing.Callable[[...], ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, help: str | None = <typer.models.DefaultPlaceholder object>, epilog: str | None = <typer.models.DefaultPlaceholder object>, short_help: str | None = <typer.models.DefaultPlaceholder object>, options_metavar: str = <typer.models.DefaultPlaceholder object>, add_help_option: bool = <typer.models.DefaultPlaceholder object>, hidden: bool = <typer.models.DefaultPlaceholder object>, deprecated: bool = <typer.models.DefaultPlaceholder object>, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, **kwargs: ~typing.Dict[str, ~typing.Any]) Callable[[Callable[[...], Any]], GroupFunction]

A function decorator that creates a new subgroup and attaches it to the root command group. This is like creating a new Typer app and adding it to a parent Typer app. The kwargs are passed through to the Typer() constructor. The group() functions work like initialize() functions for their command groups.

management/commands/example.py
from django_typer import TyperCommand, group

class Command(TyperCommand):

    @group()
    def group1(self, flag: bool = False):
        # do group init stuff here

    # to attach a command to the group, use the command() decorator
    # on the group function
    @group1.command()
    def command1(self):
        ...

    # you can also attach subgroups to groups!
    @group1.group()
    def subgroup(self):
        # do subgroup init stuff here

    @subgroup.command()
    def subcommand(self):
        ...

These groups and subcommands can be invoked from the command line like so:

$ ./manage.py example group1 --flag command1
$ ./manage.py example group1 --flag subgroup subcommand
Parameters:
  • name – the name of the group (defaults to the name of the decorated function)

  • cls – the group class to use

  • invoke_without_command – whether to invoke the group callback if no command was specified.

  • no_args_is_help – whether to show the help if no arguments are provided

  • subcommand_metavar – the metavar to use for subcommands in the help output

  • chain – whether to chain commands, this allows multiple commands from the group to be specified and run in order sequentially in one call from the command line.

  • result_callback – a callback to invoke with the result of the command

  • context_settings

    the click context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need to translate the help you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • hidden – whether to hide this group from the help output

  • deprecated – show a deprecation warning

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

django_typer.initialize(name: str | None = <typer.models.DefaultPlaceholder object>, *, cls: ~typing.Type[~django_typer.TyperGroupWrapper] = <class 'django_typer.TyperGroupWrapper'>, invoke_without_command: bool = <typer.models.DefaultPlaceholder object>, no_args_is_help: bool = <typer.models.DefaultPlaceholder object>, subcommand_metavar: str | None = <typer.models.DefaultPlaceholder object>, chain: bool = <typer.models.DefaultPlaceholder object>, result_callback: ~typing.Callable[[...], ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, help: str | None = <typer.models.DefaultPlaceholder object>, epilog: str | None = <typer.models.DefaultPlaceholder object>, short_help: str | None = <typer.models.DefaultPlaceholder object>, options_metavar: str = <typer.models.DefaultPlaceholder object>, add_help_option: bool = <typer.models.DefaultPlaceholder object>, hidden: bool = <typer.models.DefaultPlaceholder object>, deprecated: bool = <typer.models.DefaultPlaceholder object>, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, **kwargs: ~typing.Dict[str, ~typing.Any]) Callable[[Callable[[P], R]], Callable[[P], R]]

A function decorator that creates a Typer callback. This decorator wraps the Typer.callback() functionality. We’ve renamed it to initialize() because callback() is to general and not intuitive. Callbacks in Typer are functions that are invoked before a command is invoked and that can accept their own arguments. When an initialize() function is supplied to a django TyperCommand the default Django options will be added as parameters. You can specify these parameters (see django_typer.types) as arguments on the wrapped function if you wish to receive them - otherwise they will be intercepted by the base class infrastructure and used to their purpose.

The parameters are passed through to Typer.callback()

For example the below command defines two subcommands that both have a common initializer that accepts a –precision parameter option:

management/commands/math.py
 1import typing as t
 2from typer import Argument, Option
 3from django_typer import TyperCommand, initialize, command
 4
 5
 6class Command(TyperCommand):
 7
 8    precision = 2
 9
10    @initialize(help="Do some math at the given precision.")
11    def init(
12        self,
13        precision: t.Annotated[
14            int, Option(help="The number of decimal places to output.")
15        ] = precision,
16    ):
17        self.precision = precision
18
19    @command(help="Multiply the given numbers.")
20    def multiply(
21        self,
22        numbers: t.Annotated[
23            t.List[float], Argument(help="The numbers to multiply")
24        ],
25    ):
26        ...
27
28    @command()
29    def divide(
30        self,
31        numerator: t.Annotated[float, Argument(help="The numerator")],
32        denominator: t.Annotated[float, Argument(help="The denominator")]
33    ):
34        ...

When we run, the command we should provide the –precision option before the subcommand:

$ ./manage.py math --precision 5 multiply 2 2.333
4.66600
Parameters:
  • name – the name of the callback (defaults to the name of the decorated function)

  • cls – the command class to use - (the initialize() function is technically the root command group)

  • invoke_without_command – whether to invoke the callback if no command was specified.

  • no_args_is_help – whether to show the help if no arguments are provided

  • subcommand_metavar – the metavar to use for subcommands in the help output

  • chain – whether to chain commands, this allows multiple commands from the group to be specified and run in order sequentially in one call from the command line.

  • result_callback – a callback to invoke with the result of the command

  • context_settings

    the click context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need to translate the help you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • hidden – whether to hide this group from the help output

  • deprecated – show a deprecation warning

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

django_typer.model_parser_completer(model_cls: Type[Model], lookup_field: str | None = None, case_insensitive: bool = False, help_field: str | None = None, query: Callable[[ModelObjectCompleter, Context, Parameter, str], Q] | None = None, limit: int | None = 50, distinct: bool = True, on_error: Callable[[Type[Model], str, Exception], None] | None = None) Dict[str, Any]

A factory function that returns a dictionary that can be used to specify a parser and completer for a typer.Option or typer.Argument. This is a convenience function that can be used to specify the parser and completer for a model object in one go.

def handle(
    self,
    obj: t.Annotated[
        ModelClass,
        typer.Argument(
            **model_parser_completer(ModelClass, 'field_name'),
            help=_("Fetch objects by their field_names.")
        ),
    ]
):
    ...
Parameters:
  • model_cls – the model class to use for lookup

  • lookup_field – the field to use for lookup, by default the primary key

  • case_insensitive – whether to perform case insensitive lookups and completions, default: False

  • help_field – the field to use for help output in completion suggestions, by default no help will be provided

  • query – a callable that will be used to build the query for completions, by default the query will be reasonably determined by the field type

  • limit – the maximum number of completions to return, default: 50

  • distinct – whether to filter out already provided parameters in the completion suggestions, True by default

  • on_error – a callable that will be called if the parser lookup fails to produce a matching object - by default a CommandError will be raised

class django_typer.TyperCommand(stdout: TextIO | None = None, stderr: TextIO | None = None, no_color: bool = False, force_color: bool = False, **kwargs: Dict[str, Any])

An extension of BaseCommand that uses the Typer library to parse arguments and options. This class adapts BaseCommand using a light touch that relies on most of the original BaseCommand implementation to handle default arguments and behaviors.

All of the documented BaseCommand functionality works as expected. call_command also works as expected. TyperCommands however add a few extra features:

  • We define arguments and options using concise and optionally annotated type hints.

  • Simple TyperCommands implemented only using handle() can be called directly by invoking the command as a callable.

  • We can define arbitrarily complex subcommand group hierarchies using the group() and command() decorators.

  • Commands and subcommands can be fetched and invoked directly as functions using get_command()

  • We can define common initialization logic for groups of commands using initialize()

  • TyperCommands may safely return non-string values from handle()

Defining a typer command is a lot like defining a BaseCommand except that we do not have an add_arguments() method. Instead we define the parameters using type hints directly on handle():

import typing as t
from django_typer import TyperCommand

class Command(TyperCommand):

    def handle(
        self,
        arg: str,
        option: t.Optional[str] = None
    ):
        # do command logic here

TyperCommands can be extremely simple like above, or we can create really complex command group hierarchies with subcommands and subgroups (see group() and command()).

Typer apps can be configured with a number of parameters to control behavior such as exception behavior, help output, help markup interpretation, result processing and execution flow. These parameters can be passed to typer as keyword arguments in your Command class inheritance:

management/commands/chain.py
 1import typing as t
 2from django_typer import TyperCommand, command
 3
 4
 5class Command(TyperCommand, rich_markup_mode='markdown', chain=True):
 6
 7    suppressed_base_arguments = [
 8        '--verbosity', '--traceback', '--no-color', '--force-color',
 9        '--skip_checks', '--settings', '--pythonpath', '--version'
10    ]
11
12    @command()
13    def command1(self, option: t.Optional[str] = None):
14        """This is a *markdown* help string"""
15        print('command1')
16        return option
17
18    @command()
19    def command2(self, option: t.Optional[str] = None):
20        """This is a *markdown* help string"""
21        print('command2')
22        return option

We’re doing a number of things here:

We can see that our help renders like so:

./manage.py chain Usage: ./manage.py chain [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]... ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit.                                  ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ command1 This is a markdown help string                                    command2 This is a markdown help string                                    ╰──────────────────────────────────────────────────────────────────────────────╯

And we can see the chain behavior by calling our command(s) like so:

$ ./manage.py chain command1 --option one command2 --option two
command1
command2
['one', 'two']

See TyperCommandMeta for the list of accepted parameters. Also refer to the Typer docs for more information on the behaviors expected for those parameters - they are passed through to the Typer class constructor. Not all parameters may make sense in the context of a django command.

Parameters:
  • stdout – the stdout stream to use

  • stderr – the stderr stream to use

  • no_color – whether to disable color output

  • force_color – whether to force color output even if the stream is not a tty

class django_typer.TyperCommandMeta(name, bases, attrs, cls: ~typing.Type[~typer.core.TyperGroup] | None = <class 'django_typer.TyperGroupWrapper'>, invoke_without_command: bool = <typer.models.DefaultPlaceholder object>, no_args_is_help: bool = <typer.models.DefaultPlaceholder object>, subcommand_metavar: str | None = <typer.models.DefaultPlaceholder object>, chain: bool = <typer.models.DefaultPlaceholder object>, result_callback: ~typing.Callable[[...], ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, callback: ~typing.Callable[[...], ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, help: str | None = <typer.models.DefaultPlaceholder object>, epilog: str | None = <typer.models.DefaultPlaceholder object>, short_help: str | None = <typer.models.DefaultPlaceholder object>, options_metavar: str = <typer.models.DefaultPlaceholder object>, add_help_option: bool = <typer.models.DefaultPlaceholder object>, hidden: bool = <typer.models.DefaultPlaceholder object>, deprecated: bool = <typer.models.DefaultPlaceholder object>, rich_markup_mode: ~typing.Literal['markdown', 'rich', None] = None, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, pretty_exceptions_enable: ~typer.models.DefaultPlaceholder | bool = <typer.models.DefaultPlaceholder object>, pretty_exceptions_show_locals: ~typer.models.DefaultPlaceholder | bool = <typer.models.DefaultPlaceholder object>, pretty_exceptions_short: ~typer.models.DefaultPlaceholder | bool = <typer.models.DefaultPlaceholder object>)

The metaclass used to build the TyperCommand class. This metaclass is responsible for building Typer app using the arguments supplied to the TyperCommand constructor. It also discovers if handle() was supplied as the single command implementation.

Warning

This metaclass is private because it may change substantially in the future to support changes in the upstream libraries. The TyperCommand interface should be considered the stable interface.

Parameters:
  • name – the name of the class being created

  • bases – the base classes of the class being created

  • attrs – the attributes of the class being created

  • cls – The class to use as the core typer group wrapper

  • invoke_without_command – whether to invoke the group callback if no command was specified.

  • no_args_is_help – whether to show the help if no arguments are provided

  • subcommand_metavar – the metavar to use for subcommands in the help output

  • chain – whether to chain commands, this allows multiple commands from the group to be specified and run in order sequentially in one call from the command line.

  • result_callback – a callback to invoke with the result of the command

  • context_settings

    the click context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need to translate the help you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • hidden – whether to hide this group from the help output

  • deprecated – show a deprecation warning

  • rich_markup_mode – the rich markup mode to use - if rich is installed this can be used to enable rich markup or Markdown in the help output. Can be “markdown”, “rich” or None to disable markup rendering.

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

  • pretty_exceptions_enable – whether to enable pretty exceptions - if rich is installed this can be used to enable pretty exception rendering. This will default to on if the traceback configuration settings installs the rich traceback handler. This allows tracebacks to be configured by the user on a per deployment basis in the settings file. We therefore do not advise hardcoding this value.

  • pretty_exceptions_show_locals – whether to show local variables in pretty exceptions - if rich is installed. This will default to the ‘show_locals’ setting in the traceback configuration setting (on by default). This allows tracebacks to be configured by the user on a per deployment basis in the settings file. We therefore do not advise hardcoding this value.

  • pretty_exceptions_short – whether to show short tracebacks in pretty exceptions - if rich is installed. This will default to the ‘short’ setting in the traceback configuration setting (off by default). This allows tracebacks to be configured by the user on a per deployment basis in the settings file. We therefore do not advise hardcoding this value.

class django_typer.GroupFunction(*args, **kwargs)

Typer adds additional groups of commands by adding Typer apps to parent Typer apps. This class extends the typer.Typer class so that we can add the additional information necessary to attach this app to the root app and other groups specified on the django command.

command(name: str | None = None, *, cls: ~typing.Type[~typer.core.TyperCommand] = <class 'django_typer.TyperCommandWrapper'>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = None, help: str | None = None, epilog: str | None = None, short_help: str | None = None, options_metavar: str = '[OPTIONS]', add_help_option: bool = True, no_args_is_help: bool = False, hidden: bool = False, deprecated: bool = False, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, **kwargs: ~typing.Dict[str, ~typing.Any]) Callable[[Callable[[P], R]], Callable[[P], R]]

A function decorator that creates a new command and attaches it to this group. This is a passthrough to Typer.command() and the options are the same, except we swap the default command class for our wrapper.

The decorated function is the command function. It may also be invoked directly as a method from an instance of the django command class.

class Command(TyperCommand):

    @group()
    def group1(self):
        pass

    @group1.command()
    def command1(self):
        # do stuff here

Note

If you need to use a different command class you will need to either inherit from django-typer or make sure yours is interface compatible with our extensions. You shouldn’t need to do this though - if the library does not do something you need it to please submit an issue.

Parameters:
  • name – the name of the command (defaults to the name of the decorated function)

  • cls – the command class to use

  • context_settings

    the context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need the help to be translated you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • no_args_is_help – whether to show the help if no arguments are provided

  • hidden – whether to hide the command from help output

  • deprecated – show a deprecation warning

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

group(name: str | None = <typer.models.DefaultPlaceholder object>, cls: ~typing.Type[~typer.core.TyperGroup] = <class 'django_typer.TyperGroupWrapper'>, invoke_without_command: bool = <typer.models.DefaultPlaceholder object>, no_args_is_help: bool = <typer.models.DefaultPlaceholder object>, subcommand_metavar: str | None = <typer.models.DefaultPlaceholder object>, chain: bool = <typer.models.DefaultPlaceholder object>, result_callback: ~typing.Callable[[...], ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, context_settings: ~typing.Dict[~typing.Any, ~typing.Any] | None = <typer.models.DefaultPlaceholder object>, help: str | None = <typer.models.DefaultPlaceholder object>, epilog: str | None = <typer.models.DefaultPlaceholder object>, short_help: str | None = <typer.models.DefaultPlaceholder object>, options_metavar: str = <typer.models.DefaultPlaceholder object>, add_help_option: bool = <typer.models.DefaultPlaceholder object>, hidden: bool = <typer.models.DefaultPlaceholder object>, deprecated: bool = <typer.models.DefaultPlaceholder object>, rich_help_panel: str | None = <typer.models.DefaultPlaceholder object>, **kwargs: ~typing.Dict[str, ~typing.Any]) Callable[[Callable[[...], Any]], GroupFunction]

Create a new subgroup and attach it to this group. This is like creating a new Typer app and adding it to a parent Typer app. The kwargs are passed through to the Typer() constructor.

class Command(TyperCommand):

    @group()
    def group1(self):
        pass

    @group1.group()
    def subgroup(self):
        # do common group init stuff here

    @subgroup.command(help=_('My command does good stuff!'))
    def subcommand(self):
        # do command stuff here
Parameters:
  • name – the name of the group

  • cls – the group class to use

  • invoke_without_command – whether to invoke the group callback if no command was specified.

  • no_args_is_help – whether to show the help if no arguments are provided

  • subcommand_metavar – the metavar to use for subcommands in the help output

  • chain – whether to chain commands, this allows multiple commands from the group to be specified and run in order sequentially in one call from the command line.

  • result_callback – a callback to invoke with the result of the command

  • context_settings

    the click context settings to use - see click docs.

  • help – the help string to use, defaults to the function docstring, if you need to translate the help you should use the help kwarg instead because docstrings will not be translated.

  • epilog – the epilog to use in the help output

  • short_help – the short help to use in the help output

  • options_metavar – the metavar to use for options in the help output

  • add_help_option – whether to add the help option to the command

  • hidden – whether to hide this group from the help output

  • deprecated – show a deprecation warning

  • rich_help_panel – the rich help panel to use - if rich is installed this can be used to group commands into panels in the help output.

types

Common types for command line argument specification.

django_typer.types.ForceColor

The type hint for the Django –force-color option.

The –force-color option is included by default and behaves the same as on BaseCommand use it to force colorization of the command. You can check the supplied value of –force-color by checking the force_color attribute of the command instance.

alias of Annotated[bool]

django_typer.types.NoColor

The type hint for the Django –no-color option.

The –no-color option is included by default and behaves the same as on BaseCommand use it to force disable colorization of the command. You can check the supplied value of –no-color by checking the no_color attribute of the command instance.

alias of Annotated[bool]

django_typer.types.PythonPath

The type hint for the Django –pythonpath option.

The –pythonpath option is included by default and behaves the same as on BaseCommand use it to specify a directory to add to the Python sys path.

alias of Annotated[Path | None]

django_typer.types.Settings

The type hint for the Django –settings option.

The –settings option is included by default and behaves the same as on BaseCommand use it to specify or override the settings module to use.

alias of Annotated[str]

django_typer.types.SkipChecks

The type hint for the Django –skip-checks option.

The –skip-checks option is included by default and behaves the same as on BaseCommand use it to skip system checks.

alias of Annotated[bool]

django_typer.types.Traceback

The type hint for the Django –traceback option.

The –traceback option is included by default and behaves the same as on BaseCommand use it to allow CommandError exceptions to propagate out of the command and produce a stack trace.

alias of Annotated[bool]

django_typer.types.Verbosity

The type hint for the Django –verbosity option. TyperCommand does not include the verbosity option by default, but it can be added to the command like so if needed.

from django_typer.types import Verbosity

def handle(self, verbosity: Verbosity = 1):
    ...

alias of Annotated[int]

django_typer.types.Version

The type hint for the Django –version option.

The –version option is included by default and behaves the same as on BaseCommand.

alias of Annotated[bool]

django_typer.types.print_version(context, _, value)

A callback to run the get_version() routine of the command when –version is specified.

django_typer.types.set_force_color(context, param, value)

If the value was provided set it on the command.

django_typer.types.set_no_color(context, param, value)

If the value was provided set it on the command.

parsers

Typer supports custom parsers for options and arguments. If you would like to type a parameter with a type that isn’t supported by Typer you can implement your own parser , or ParamType in click parlance.

This module contains a collection of parsers that turn strings into useful Django types. Pass these parsers to the parser argument of typer.Option and typer.Argument. Parsers are provided for:

Warning

If you implement a custom parser, please take care to ensure that it:
  • Handles the case where the value is already the expected type.

  • Returns None if the value is None (already implemented if subclassing ParamType).

  • Raises a CommandError if the value is invalid.

  • Handles the case where the param and context are None.

class django_typer.parsers.ModelObjectParser(model_cls: Type[Model], lookup_field: str | None = None, case_insensitive: bool = False, on_error: Callable[[Type[Model], str, Exception], None] | None = None)

A parser that will turn strings into model object instances based on the configured lookup field and model class.

from django_typer.parsers import ModelObjectParser

class Command(TyperCommand):
    def handle(
        self,
        django_apps: Annotated[
            t.List[MyModel],
            typer.Argument(
                parser=ModelObjectParser(MyModel, lookup_field="name"),
                help=_("One or more application labels."),
            ),
        ],
    ):

Note

Typer does not respect the shell_complete functions on ParamTypes passed as parsers. To add shell_completion see ModelObjectCompleter or the model_parser_completer() convenience function.

Parameters:
  • model_cls – The model class to use for lookup.

  • lookup_field – The field to use for lookup. Defaults to ‘pk’.

  • on_error – A callable that will be called if the lookup fails. The callable should accept three arguments: the model class, the value that failed to lookup, and the exception that was raised. If not provided, a CommandError will be raised.

convert(value: Any, param: Parameter | None, ctx: Context | None)

Invoke the parsing action on the given string. If the value is already a model instance of the expected type the value will be returned. Otherwise the value will be treated as a value to query against the lookup_field. If no model object is found the error handler is invoked if one was provided.

Parameters:
  • value – The value to parse.

  • param – The parameter that the value is associated with.

  • ctx – The context of the command.

Raises:

CommandError – If the lookup fails and no error handler is provided.

django_typer.parsers.parse_app_label(label: str | AppConfig)

A parser for app labels. If the label is already an AppConfig instance, the instance is returned. The label will be tried first, if that fails the label will be treated as the app name.

import typing as t
import typer
from django_typer import TyperCommand
from django_typer.parsers import parse_app_label

class Command(TyperCommand):

    def handle(
        self,
        django_apps: t.Annotated[
            t.List[AppConfig],
            typer.Argument(
                parser=parse_app_label,
                help=_("One or more application labels.")
            )
        ]
    ):
        ...
Parameters:

label – The label to map to an AppConfig instance.

Raises:

CommandError – If no matching app can be found.

completers

Typer and click provide tab-completion hooks for individual parameters. As with parsers custom completion logic can be implemented for custom parameter types and added to the annotation of the parameter. Previous versions of Typer supporting click 7 used the autocompletion argument to provide completion logic, Typer still supports this, but passing shell_complete to the annotation is the preferred way to do this.

This module provides some completer functions and classes that work with common Django types:

class django_typer.completers.ModelObjectCompleter(model_cls: Type[Model], lookup_field: str | None = None, help_field: str | None = None, query: Callable[[ModelObjectCompleter, Context, Parameter, str], Q] | None = None, limit: int | None = 50, case_insensitive: bool = False, distinct: bool = True)

A completer for generic Django model objects. This completer will work for most Django core model field types where completion makes sense.

This completer currently supports the following field types and their subclasses:

The completer query logic is pluggable, but the defaults cover most use cases. The limit field is important. It defaults to 50 meaning if more than 50 potential completions are found only the first 50 will be returned and there will be no indication to the user that there are more. This is to prevent the shell from becoming unresponsive when offering completion for large tables.

To use this completer, pass an instance of this class to the shell_complete argument of a typer.Option or typer.Argument:

from django_typer.completers import ModelObjectCompleter

class Command(TyperCommand):

    def handle(
        self,
        model_obj: Annotated[
            MyModel,
            typer.Argument(
                shell_complete=ModelObjectCompleter(MyModel, lookup_field="name"),
                help=_("The model object to use.")
            )
        ]
    ):
        ...

Note

See also model_parser_completer() for a convenience function that returns a configured parser and completer for a model object and helps reduce boilerplate.

Parameters:
  • model_cls – The Django model class to query.

  • lookup_field – The name of the model field to use for lookup.

  • help_field – The name of the model field to use for help text or None if no help text should be provided.

  • query – A callable that accepts the completer object instance, the click context, the click parameter, and the incomplete string and returns a Q object to use for filtering the queryset. The default query will use the relevant class methods depending on the lookup field class. See the query methods for details.

  • limit – The maximum number of completion items to return. If None, all matching items will be returned. When offering completion for large tables you’ll want to set this to a reasonable limit. Default: 50

  • case_insensitive – Whether or not to perform case insensitive matching when completing text-based fields. Defaults to False.

  • distinct – Whether or not to filter out duplicate values. Defaults to True. This is not the same as calling distinct() on the queryset - which will happen regardless - but rather whether or not to filter out values that are already given for the parameter on the command line.

float_query(context: Context, parameter: Parameter, incomplete: str) Q

The default completion query builder for float fields. This method will return a Q object that will match any value that starts with the incomplete string. For example, if the incomplete string is “1.1”, the query will match 1.1 <= float(incomplete) < 1.2

Parameters:
  • context – The click context.

  • parameter – The click parameter.

  • incomplete – The incomplete string.

Returns:

A Q object to use for filtering the queryset.

Raises:
  • ValueError – If the incomplete string is not a valid float.

  • TypeError – If the incomplete string is not a valid float.

int_query(context: Context, parameter: Parameter, incomplete: str) Q

The default completion query builder for integer fields. This method will return a Q object that will match any value that starts with the incomplete string. For example, if the incomplete string is “1”, the query will match 1, 10-19, 100-199, 1000-1999, etc.

Parameters:
  • context – The click context.

  • parameter – The click parameter.

  • incomplete – The incomplete string.

Returns:

A Q object to use for filtering the queryset.

Raises:
  • ValueError – If the incomplete string is not a valid integer.

  • TypeError – If the incomplete string is not a valid integer.

text_query(context: Context, parameter: Parameter, incomplete: str) Q

The default completion query builder for text-based fields. This method will return a Q object that will match any value that starts with the incomplete string. Case sensitivity is determined by the case_insensitive constructor parameter.

Parameters:
  • context – The click context.

  • parameter – The click parameter.

  • incomplete – The incomplete string.

Returns:

A Q object to use for filtering the queryset.

uuid_query(context: Context, parameter: Parameter, incomplete: str) Q

The default completion query builder for UUID fields. This method will return a Q object that will match any value that starts with the incomplete string. The incomplete string will be stripped of all non-alphanumeric characters and padded with zeros to 32 characters. For example, if the incomplete string is “a”, the query will match a0000000-0000-0000-0000-000000000000 to affffffff-ffff-ffff-ffff-ffffffffffff.

Parameters:
  • context – The click context.

  • parameter – The click parameter.

  • incomplete – The incomplete string.

Returns:

A Q object to use for filtering the queryset.

Raises:

ValueError – If the incomplete string is too long or contains invalid UUID characters. Anything other than (0-9a-fA-F).

django_typer.completers.complete_app_label(ctx: Context, param: Parameter, incomplete: str) List[CompletionItem]

A case-sensitive completer for Django app labels or names. The completer prefers labels but names will also work.

import typing as t
import typer
from django_typer import TyperCommand
from django_typer.parsers import parse_app_label
from django_typer.completers import complete_app_label

class Command(TyperCommand):

    def handle(
        self,
        django_apps: t.Annotated[
            t.List[AppConfig],
            typer.Argument(
                parser=parse_app_label,
                shell_complete=complete_app_label,
                help=_("One or more application labels.")
            )
        ]
    ):
        ...
Parameters:
  • ctx – The click context.

  • param – The click parameter.

  • incomplete – The incomplete string.

Returns:

A list of matching app labels or names. Labels already present for the parameter on the command line will be filtered out.

utils

A collection of useful utilities.

django_typer.utils.get_current_command() TyperCommand | None

Returns the current typer command. This can be used as a way to access the current command object from anywhere if we are executing inside of one from higher on the stack. We primarily need this because certain monkey patches are required in typer code - namely for enabling/disabling color based on configured parameters.

This function is thread safe.

This is analogous to click’s get_current_context but for command execution.

Returns:

The current typer command or None if there is no active command.

django_typer.utils.traceback_config() bool | Dict[str, Any]

Fetch the rich traceback installation parameters from our settings. By default rich tracebacks are on with show_locals = True. If the config is set to False or None rich tracebacks will not be installed even if the library is present.

This allows us to have a common traceback configuration for all commands. If rich tracebacks are managed separately this setting can also be switched off.

shellcompletion

The shellcompletion command is a Django management command that installs and removes shellcompletion scripts for supported shells (bash, fish, zsh, powershell). This command is also the entry point for running the completion logic and can be used to debug completer code.

manage.py shellcompletion Usage: manage.py shellcompletion [OPTIONS] COMMAND [ARGS]... Install autocompletion for the current shell. ╭─ Options ────────────────────────────────────────────────────────────────────╮ --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Django ─────────────────────────────────────────────────────────────────────╮ --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 ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ complete Generate autocompletion for command string.                       install  Install autocompletion for the current or given shell.            remove   Remove autocompletion for the current or given shell.             ╰──────────────────────────────────────────────────────────────────────────────╯

install() invokes typer’s shell completion installation logic, but does have to patch the installed scripts. This is because there is only one installation for all Django management commands, not each individual command. The completion logic here will failover to Django’s builtin autocomplete if the command in question is not a TyperCommand. To promote compatibility with other management command libraries or custom completion logic, a fallback completion function can also be specified.

class django_typer.management.commands.shellcompletion.Command(stdout: TextIO | None = None, stderr: TextIO | None = None, no_color: bool = False, force_color: bool = False, **kwargs: Dict[str, Any])

This command installs autocompletion for the current shell. This command uses the typer/click autocompletion scripts to generate the autocompletion items, but monkey patches the scripts to invoke our bundled shell complete script which fails over to the django autocomplete function when the command being completed is not a TyperCommand. When the django autocomplete function is used we also wrap it so that it works for any supported click/typer shell, not just bash.

We also provide a remove command to easily remove the installed script.

Great pains are taken to use the upstream dependency’s shell completion logic. This is so advances and additional shell support implemented upstream should just work. However, it would be possible to add support for new shells here using the pluggable logic that click provides. It is probably a better idea however to add support for new shells at the typer level.

Shell autocompletion can be brittle with every shell having its own quirks and nuances. We make a good faith effort here to support all the shells that typer/click support, but there can easily be system specific configuration issues that prevent this from working. In those cases users should refer to the online documentation for their specific shell to troubleshoot.

complete(cmd_str: str | None = None, shell: Shells | None = None, fallback: str | None = None)

We implement the shell complete generation script as a Django command because the Django environment needs to be bootstrapped for it to work. This also allows us to test completion logic in a platform agnostic way.

Tip

This command is super useful for debugging shell_complete logic. For example to enter into the debugger, we could set a breakpoint in our shell_complete function for the option parameter and then run the following command:

$ ./manage.py shellcompletion complete "./manage.py your_command --option "
shellcompletion shellcompletion Usage: shellcompletion shellcompletion [OPTIONS] command Generate autocompletion for command string. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ cmd_strcommandThe command string to generate completion            suggestions for.                                     [default: None]                                      ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --shell[bash|zsh|fish|powershell|pSpecify the shell to fetch    wsh]completion for, default will  autodetect.                   [default: None]               --fallbackTEXT                       The python import path to a   fallback complete function to use when the completion       command is not a              TyperCommand. By default, the builtin django autocomplete   function is used.             [default: None]               --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯
django_fallback()

Run django’s builtin bash autocomplete function. We wrap the click completion class to make it work for all supported shells, not just bash.

install(shell: Shells | None = 'sh', manage_script: str | None = None, fallback: str | None = None)

Install autocompletion for the given shell. If the shell is not specified, it will try to detect the shell. If the shell is not detected, it will fail.

We run the upstream typer installation routines, with some augmentation.

shellcompletion install Usage: shellcompletion install [OPTIONS] [SHELL]:[bash|zsh|fish|powershell|pwsh] Install autocompletion for the current or given shell. ╭─ Arguments ───────────────────────────────────────────────────────────────────────╮ shell[SHELL]:[bash|zsh|fish|powershellSpecify the shell to install or   |pwsh]remove autocompletion for.        [default: sh]                     ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ─────────────────────────────────────────────────────────────────────────╮ --manage-scriptTEXTThe name of the django manage script to install      autocompletion for if different than the script used to invoke this command.                              [default: None]                                      --fallbackTEXTThe python import path to a fallback complete        function to use when the completion command is not a TyperCommand.                                        [default: None]                                      --helpShow this message and exit. ╰───────────────────────────────────────────────────────────────────────────────────╯
property manage_script: str | Path

Returns the name of the manage command as a string if it is available as a command on the user path. If it is a script that is not available as a command on the path it will return an absolute Path object to the script.

property manage_script_name: str

Get the name of the manage script as a command available from the shell’s path.

noop()

This is a no-op command that is used to bootstrap click Completion classes. It has no use other than to avoid any potential attribute access errors when we spoof completion logic

property noop_command

This is a no-op command that is used to bootstrap click Completion classes. It has no use other than to avoid any potential attribute errors when we emulate upstream completion logic

patch_script(shell: Shells | None = None, fallback: str | None = None) None

We have to monkey patch the typer completion scripts to point to our custom shell complete script. This is potentially brittle but thats why we have robust CI!

Parameters:
  • shell – The shell to patch the completion script for.

  • fallback – The python import path to a fallback autocomplete function to use when the completion command is not a TyperCommand. Defaults to None, which means the bundled complete script will fallback to the django autocomplete function, but wrap it so it works for all supported shells other than just bash.

remove(shell: Shells | None = 'sh', manage_script: str | None = None)

Remove the autocompletion for the given shell. If the shell is not specified, it will try to detect the shell. If the shell is not detected, it will fail.

Since the installation routine is upstream we first run install to determine where the completion script is installed and then we remove it.

shellcompletion shellcompletion Usage: shellcompletion shellcompletion [OPTIONS]                                        [SHELL]:[bash|zsh|fish|powershell|pwsh] Remove autocompletion for the current or given shell. ╭─ Arguments ──────────────────────────────────────────────────────────────────╮ shell[SHELL]:[bash|zsh|fish|powershSpecify the shell to install or ell|pwsh]remove shell completion for.    [default: sh]                   ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────╮ --manage-scriptTEXTThe name of the django manage script to remove  shell completion for if different than the      script used to invoke this command.             [default: None]                                 --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯
property shell: Shells

Get the active shell. If not explicitly set, it first tries to find the shell in the environment variable shell complete scripts set and failing that it will try to autodetect the shell.