Skip to content

register_command

register_command

register_command(
    name: str | None = None,
    *,
    group: str | None = None,
    permission: str | list[str] = "superuser",
    params: list | None = None,
    exclude_params: list | None = None,
    models: list | None = None,
    widgets: dict | None = None,
    form_class=None,
    display_name: str | None = None,
)

Decorator to register a management command with the admin runner.

Parameters:

Name Type Description Default
name str | None

Command name. Defaults to the command's module name.

None
group str | None

Group label shown in the admin list. Defaults to the app label.

None
permission str | list[str]

Who may run this command. "superuser" (default) restricts to superusers only. Pass a Django permission string such as "myapp.change_mymodel" or a list of permission strings (all must be held — AND logic). Superusers always bypass permission checks.

'superuser'
params list | None

Allowlist of argument dest names to include in the generated form. All others are excluded.

None
exclude_params list | None

Denylist of argument dest names to exclude from the generated form.

None
models list | None

List of Django model classes. A "Run" link for this command will appear on each model's admin change-list page when CommandRunnerModelAdminMixin is used.

None
widgets dict | None

Per-parameter widget or field overrides. Keys are argument dest names; values are either a :class:~django.forms.Widget instance (swaps the widget on the auto-detected field) or a :class:~django.forms.Field instance (replaces the auto-detected field entirely, e.g. FileOrPathField(), forms.FileField(), forms.ImageField()). The widget= kwarg on add_argument takes priority over this dict. Unfold widget auto-replacement is skipped for parameters that have an entry here.

None
form_class

A fully custom :class:~django.forms.Form class. When set, form_from_command returns it directly — all auto-generation, params/exclude_params filtering, and Unfold widget replacement are bypassed.

None
display_name str | None

Human-readable name for the command. Defaults to the command name with underscores replaced by spaces and title-cased (e.g., "import_books""Import Books").

None
Source code in src/django_admin_runner/registry.py
def register_command(
    name: str | None = None,
    *,
    group: str | None = None,
    permission: str | list[str] = "superuser",
    params: list | None = None,
    exclude_params: list | None = None,
    models: list | None = None,
    widgets: dict | None = None,
    form_class=None,
    display_name: str | None = None,
):
    """
    Decorator to register a management command with the admin runner.

    Args:
        name: Command name. Defaults to the command's module name.
        group: Group label shown in the admin list. Defaults to the app label.
        permission: Who may run this command. ``"superuser"`` (default) restricts
            to superusers only. Pass a Django permission string such as
            ``"myapp.change_mymodel"`` or a list of permission strings (all must
            be held — AND logic). Superusers always bypass permission checks.
        params: Allowlist of argument ``dest`` names to include in the generated
            form. All others are excluded.
        exclude_params: Denylist of argument ``dest`` names to exclude from the
            generated form.
        models: List of Django model classes. A "Run" link for this command will
            appear on each model's admin change-list page when
            ``CommandRunnerModelAdminMixin`` is used.
        widgets: Per-parameter widget or field overrides. Keys are argument
            ``dest`` names; values are either a
            :class:`~django.forms.Widget` instance (swaps the widget on the
            auto-detected field) or a :class:`~django.forms.Field` instance
            (replaces the auto-detected field entirely, e.g.
            ``FileOrPathField()``, ``forms.FileField()``,
            ``forms.ImageField()``).  The ``widget=`` kwarg on ``add_argument``
            takes priority over this dict.  Unfold widget auto-replacement is
            skipped for parameters that have an entry here.
        form_class: A fully custom :class:`~django.forms.Form` class. When set,
            ``form_from_command`` returns it directly — all auto-generation,
            ``params``/``exclude_params`` filtering, and Unfold widget
            replacement are bypassed.
        display_name: Human-readable name for the command. Defaults to the
            command name with underscores replaced by spaces and title-cased
            (e.g., ``"import_books"`` → ``"Import Books"``).
    """

    def decorator(cls):
        cmd_name = name or _module_to_command_name(cls.__module__)
        app_label = _module_to_app_label(cls.__module__)
        _registry[cmd_name] = {
            "name": cmd_name,
            "group": group or app_label,
            "permission": permission,
            "params": params,
            "exclude_params": list(exclude_params or []),
            "models": list(models or []),
            "widgets": dict(widgets or {}),
            "form_class": form_class,
            "command_class": cls,
            "app_label": app_label,
            "display_name": display_name or cmd_name.replace("_", " ").title(),
        }
        return cls

    return decorator