paduszyk / django-management-commands

👨🏻‍💻 Modular discovery, aliasing, and sequencing of Django management commands ⚡️
MIT License
4 stars 1 forks source link
django django-application django-commands django-management-commands python

django-management-commands

PyPI: Version PyPI: Python PyPI: Django PyPI: License

Pre-commit.ci CI Codecov

Nox Ruff Mypy Prettier Conventional Commits

Overview

django-management-commands is a plugin that provides enhanced flexibility for defining, organizing, and executing Django commands.

While Django enforces certain conventions for management commands, this package allows you to bypass these limitations. With django-management-commands, you can define and manage commands outside the traditional management.commands package, giving you greater freedom in structuring your project. This is especially useful for developers working on large projects with multiple apps or complex command structures, where organizing commands effectively is critical.

Key Features

Requirements

This package supports the following Python and Django versions:

Python Django
3.9 4.2
3.10 4.2, 5.0, 5.1
3.11 4.2, 5.0, 5.1
3.12 4.2, 5.0, 5.1

Configuration is managed through django-appconf ~= 1.0.

Installation

To install the plugin, download and install it from PyPI using pip:

pip install django-management-commands

You can also use any other dependency manager of your choice. Once installed, you can access the plugin's features through the management_commands package.

We recommend avoiding global or system-wide Python environments for package installation. Always use a virtual environment to manage your dependencies.

Django Setup

To enable advanced command management features, update your project's starter script; this file is likely named manage.py. Replace the line that refers to Django's management utility:

from django.core.management import execute_from_command_line

with:

from management_commands.management import execute_from_command_line

That's it! No further steps are needed.

Usage

Running Commands

The plugin does not change how commands are executed, but rather how they are discovered. Running commands works the same way as with Django's built-in utility.

Additionally, you can invoke commands registered from INSTALLED_APPS using a more explicit notation that accounts for the app label:

python manage.py <APP_LABEL>.<COMMAND>

This is particularly useful when multiple apps register commands with the same name. If no app label is provided, the plugin attempts to auto-discover the command's module and class in custom paths, modules, submodules, and aliases, as described in the Configuration section.

Configuration

The plugin provides several optional settings to customize the discovery and execution of Django commands via DJANGO_SETTINGS_MODULE.

MANAGEMENT_COMMANDS_PATHS

Type: dict[str, str]

Default: {}

This setting maps custom command names to their corresponding class paths, allowing you to define commands outside the standard app structure.

Example:

MANAGEMENT_COMMANDS_PATHS = {
    "my-command": "mysite.commands.MyCommand",
}

You can now run the custom command my-command implemented in the MyCommand class from the mysite.commands module:

python manage.py my-command

In Django, the class representing a command must be named Command. The plugin allows you to name it with any valid Python identifier, enabling multiple commands within a single module.

Important Notes:

MANAGEMENT_COMMANDS_MODULES

Type: list[str]

Default: []

Specifies the modules where custom commands should be discovered.

Example:

MANAGEMENT_COMMANDS_MODULES = [
    "mycommands",
]

When running:

python manage.py mycommand

the utility will search for the Command class in the mycommands.mycommand module.

Important Notes:

MANAGEMENT_COMMANDS_SUBMODULES

Type: list[str]

Default: []

Defines submodules within app packages where commands should be discovered. Django's default management.commands is automatically inserted at index 0 if not explicitly included.

Example:

MANAGEMENT_COMMANDS_SUBMODULES = [
    "commands",
]

This allows the utility to search for Command classes in both myapp.management.commands.command and myapp.commands.command for an app installed from the myapp module.

Important Notes:

MANAGEMENT_COMMANDS_ALIASES

Type: dict[str, list[str]]

Default: {}

Allows the definition of shortcuts or aliases for sequences of Django commands.

Example:

MANAGEMENT_COMMANDS_ALIASES = {
    "full-check": [
        "check --fail-level ERROR --deploy",
        "makemigrations --check --dry-run --no-input",
        "migrate --no-input",
    ],
}

You can now execute all the commands aliased by full-check with a single command:

python manage.py full-check

Aliases can refer to commands defined in the MANAGEMENT_COMMANDS_PATHS setting or other aliases.

Important Notes:

Error Handling

Configuration Checks

The plugin performs basic validation of user settings, primarily checking command names, aliases, and module paths. If any checks fail, the plugin raises an ImproperlyConfigured error.

For more information, see the management_commands.conf module.

The ImproperlyConfigured error here is distinct from the one in django.core.exceptions; the plugin's uses its own exception class defined with its configuration.

Custom Exceptions

The package includes custom exceptions for error handling:

For more information, see the management_commands.exceptions module.

Be sure to review these exceptions when debugging or reporting issues.

Contributing

License

Released under the MIT license.