django-management-commands


Namedjango-management-commands JSON
Version 1.1.0 PyPI version JSON
download
home_pageNone
SummaryModular discovery, aliasing, and sequencing of Django commands
upload_time2024-09-25 09:31:29
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseNone
keywords django django-application django-commands django-management-commands
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-management-commands

[![PyPI: Version](https://img.shields.io/pypi/v/django-management-commands?logo=pypi&logoColor=white)][pypi]
[![PyPI: Python](https://img.shields.io/pypi/pyversions/django-management-commands?logo=python&logoColor=white)][pypi]
[![PyPI: Django](https://img.shields.io/pypi/djversions/django-management-commands?logo=django&label=django&color=0c4b33)][pypi]
[![PyPI: License](https://img.shields.io/pypi/l/django-management-commands)][pypi]

[![Pre-commit.ci](https://results.pre-commit.ci/badge/github/paduszyk/django-management-commands/main.svg)][pre-commit.ci]
[![CI](https://img.shields.io/github/actions/workflow/status/paduszyk/django-management-commands/package-ci.yml?logo=github&label=CI)][ci]
[![Codecov](https://img.shields.io/codecov/c/github/paduszyk/django-management-commands?logo=codecov)][codecov]

[![Nox](https://img.shields.io/badge/%f0%9f%a6%8a-Nox-d85e00)][nox]
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)][ruff]
[![Mypy](https://img.shields.io/badge/type--checked-mypy-blue?logo=python)][mypy]
[![Prettier](https://img.shields.io/badge/code_style-Prettier-1e2b33?logo=prettier)][prettier]
[![Conventional Commits](https://img.shields.io/badge/Conventional_Commits-1.0.0-fa6673?logo=conventional-commits)][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][django-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

- **Flexible Command Location**: Define commands in any module, allowing you to
  organize your codebase more freely without relying on Django's default structure.

- **Custom Command Naming**: Assign names to commands independently of their submodules,
  enabling clearer and more intuitive command management.

- **Command Name Conflicts Resolution**: Resolve command name conflicts by referencing
  commands through app labels.

- **Enhanced Command Management**: Define, organize, and execute commands or aliases
  via your Django settings, simplifying complex command sequences and improving
  maintainability.

## 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`][django-appconf].

## Installation

To install the plugin, download and install it from [PyPI][pypi] using `pip`:

```console
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:

```python
from django.core.management import execute_from_command_line
```

with:

```python
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:

```console
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](#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:

```python
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:

```console
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:**

- All keys and values must be valid Python identifiers (with hyphens allowed) and
  absolute dotted paths, respectively.
- Paths must point to command classes, not modules.
- Commands must subclass `django.core.management.base.BaseCommand`.
- This setting takes precedence over others when discovering commands.

#### `MANAGEMENT_COMMANDS_MODULES`

**Type:** `list[str]`

**Default:** `[]`

Specifies the modules where custom commands should be discovered.

Example:

```python
MANAGEMENT_COMMANDS_MODULES = [
    "mycommands",
]
```

When running:

```console
python manage.py mycommand
```

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

**Important Notes:**

- Items must be valid absolute dotted Python paths.
- Commands are discovered in modules in the order they are listed.

#### `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:

```python
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:**

- Items must be valid absolute dotted Python paths (although at runtime, they are
  treated as relative paths appended to app names).

#### `MANAGEMENT_COMMANDS_ALIASES`

**Type:** `dict[str, list[str]]`

**Default:** `{}`

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

Example:

```python
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:

```console
python manage.py full-check
```

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

**Important Notes:**

- Keys must be valid Python identifiers (with hyphens allowed).
- Values should be command expressions with parsable arguments and options.
- Circular references within aliases are not allowed, as they lead to infinite recursion.

### 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:

- **`CommandImportError`**: raised if the command class import fails;

- **`CommandTypeError`**: raised if the imported command class is not a subclass
  of Django's `BaseCommand`;

- **`CommandClassLookupError`**: raised if a command cannot be discovered;

- **`CommandAppLookupError`**: raised when a command is referenced by app label,
  but the app with that label is not installed.

For more information, see the `management_commands.exceptions` module.

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

## Contributing

- This is an open-source project and welcomes all types of contributions.
- Contributors must adhere to our [Code of Conduct][code-of-conduct].
- For detailed contribution guidelines, please refer to our [Contributing Guide][contributing].

## License

Released under the [MIT license][license].

[ci]: https://github.com/paduszyk/django-management-commands/actions/workflows/package-ci.yml
[code-of-conduct]: https://github.com/paduszyk/django-management-commands/blob/main/docs/CODE_OF_CONDUCT.md
[codecov]: https://app.codecov.io/gh/paduszyk/django-management-commands
[contributing]: https://github.com/paduszyk/django-management-commands/blob/main/docs/CONTRIBUTING.md
[conventional-commits]: https://www.conventionalcommits.org/
[django-appconf]: https://github.com/django-compressor/django-appconf
[django-commands]: https://docs.djangoproject.com/en/dev/howto/custom-management-commands/
[license]: https://github.com/paduszyk/django-management-commands/blob/main/LICENSE
[mypy]: https://mypy.readthedocs.io
[nox]: https://nox.thea.codes/
[pre-commit.ci]: https://results.pre-commit.ci/latest/github/paduszyk/django-management-commands/main
[prettier]: https://prettier.io
[pypi]: https://pypi.org/project/django-management-commands/
[ruff]: https://docs.astral.sh/ruff/

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-management-commands",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "django, django-application, django-commands, django-management-commands",
    "author": null,
    "author_email": "Kamil Paduszy\u0144ski <92403542+paduszyk@users.noreply.github.com>",
    "download_url": "https://files.pythonhosted.org/packages/13/78/4f199fbbde6a7d114238297fe3a7fafcbfb593514b5b53271a268dce1fe0/django_management_commands-1.1.0.tar.gz",
    "platform": null,
    "description": "# django-management-commands\n\n[![PyPI: Version](https://img.shields.io/pypi/v/django-management-commands?logo=pypi&logoColor=white)][pypi]\n[![PyPI: Python](https://img.shields.io/pypi/pyversions/django-management-commands?logo=python&logoColor=white)][pypi]\n[![PyPI: Django](https://img.shields.io/pypi/djversions/django-management-commands?logo=django&label=django&color=0c4b33)][pypi]\n[![PyPI: License](https://img.shields.io/pypi/l/django-management-commands)][pypi]\n\n[![Pre-commit.ci](https://results.pre-commit.ci/badge/github/paduszyk/django-management-commands/main.svg)][pre-commit.ci]\n[![CI](https://img.shields.io/github/actions/workflow/status/paduszyk/django-management-commands/package-ci.yml?logo=github&label=CI)][ci]\n[![Codecov](https://img.shields.io/codecov/c/github/paduszyk/django-management-commands?logo=codecov)][codecov]\n\n[![Nox](https://img.shields.io/badge/%f0%9f%a6%8a-Nox-d85e00)][nox]\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)][ruff]\n[![Mypy](https://img.shields.io/badge/type--checked-mypy-blue?logo=python)][mypy]\n[![Prettier](https://img.shields.io/badge/code_style-Prettier-1e2b33?logo=prettier)][prettier]\n[![Conventional Commits](https://img.shields.io/badge/Conventional_Commits-1.0.0-fa6673?logo=conventional-commits)][conventional-commits]\n\n## Overview\n\n`django-management-commands` is a plugin that provides enhanced flexibility for\ndefining, organizing, and executing Django commands.\n\nWhile Django enforces certain conventions for [management commands][django-commands],\nthis package allows you to bypass these limitations. With `django-management-commands`,\nyou can define and manage commands outside the traditional `management.commands`\npackage, giving you greater freedom in structuring your project. This is especially\nuseful for developers working on large projects with multiple apps or complex command\nstructures, where organizing commands effectively is critical.\n\n## Key Features\n\n- **Flexible Command Location**: Define commands in any module, allowing you to\n  organize your codebase more freely without relying on Django's default structure.\n\n- **Custom Command Naming**: Assign names to commands independently of their submodules,\n  enabling clearer and more intuitive command management.\n\n- **Command Name Conflicts Resolution**: Resolve command name conflicts by referencing\n  commands through app labels.\n\n- **Enhanced Command Management**: Define, organize, and execute commands or aliases\n  via your Django settings, simplifying complex command sequences and improving\n  maintainability.\n\n## Requirements\n\nThis package supports the following Python and Django versions:\n\n| Python | Django        |\n| :----- | :------------ |\n| 3.9    | 4.2           |\n| 3.10   | 4.2, 5.0, 5.1 |\n| 3.11   | 4.2, 5.0, 5.1 |\n| 3.12   | 4.2, 5.0, 5.1 |\n\nConfiguration is managed through [`django-appconf ~= 1.0`][django-appconf].\n\n## Installation\n\nTo install the plugin, download and install it from [PyPI][pypi] using `pip`:\n\n```console\npip install django-management-commands\n```\n\nYou can also use any other dependency manager of your choice. Once installed, you\ncan access the plugin's features through the `management_commands` package.\n\n> We recommend avoiding global or system-wide Python environments for package installation.\n> Always use a virtual environment to manage your dependencies.\n\n## Django Setup\n\nTo enable advanced command management features, update your project's starter script;\nthis file is likely named `manage.py`. Replace the line that refers to Django's\nmanagement utility:\n\n```python\nfrom django.core.management import execute_from_command_line\n```\n\nwith:\n\n```python\nfrom management_commands.management import execute_from_command_line\n```\n\nThat's it! No further steps are needed.\n\n## Usage\n\n### Running Commands\n\nThe plugin does not change how commands are executed, but rather how they are discovered.\nRunning commands works the same way as with Django's built-in utility.\n\nAdditionally, you can invoke commands registered from `INSTALLED_APPS` using a more\nexplicit notation that accounts for the app label:\n\n```console\npython manage.py <APP_LABEL>.<COMMAND>\n```\n\nThis is particularly useful when multiple apps register commands with the same name.\nIf no app label is provided, the plugin attempts to auto-discover the command's\nmodule and class in custom paths, modules, submodules, and aliases, as described\nin the [Configuration](#configuration) section.\n\n### Configuration\n\nThe plugin provides several optional settings to customize the discovery and execution\nof Django commands via `DJANGO_SETTINGS_MODULE`.\n\n#### `MANAGEMENT_COMMANDS_PATHS`\n\n**Type:** `dict[str, str]`\n\n**Default:** `{}`\n\nThis setting maps custom command names to their corresponding class paths, allowing\nyou to define commands outside the standard app structure.\n\nExample:\n\n```python\nMANAGEMENT_COMMANDS_PATHS = {\n    \"my-command\": \"mysite.commands.MyCommand\",\n}\n```\n\nYou can now run the custom command `my-command` implemented in the `MyCommand` class\nfrom the `mysite.commands` module:\n\n```console\npython manage.py my-command\n```\n\n> In Django, the class representing a command must be named `Command`. The plugin\n> allows you to name it with any valid Python identifier, enabling multiple commands\n> within a single module.\n\n**Important Notes:**\n\n- All keys and values must be valid Python identifiers (with hyphens allowed) and\n  absolute dotted paths, respectively.\n- Paths must point to command classes, not modules.\n- Commands must subclass `django.core.management.base.BaseCommand`.\n- This setting takes precedence over others when discovering commands.\n\n#### `MANAGEMENT_COMMANDS_MODULES`\n\n**Type:** `list[str]`\n\n**Default:** `[]`\n\nSpecifies the modules where custom commands should be discovered.\n\nExample:\n\n```python\nMANAGEMENT_COMMANDS_MODULES = [\n    \"mycommands\",\n]\n```\n\nWhen running:\n\n```console\npython manage.py mycommand\n```\n\nthe utility will search for the `Command` class in the `mycommands.mycommand` module.\n\n**Important Notes:**\n\n- Items must be valid absolute dotted Python paths.\n- Commands are discovered in modules in the order they are listed.\n\n#### `MANAGEMENT_COMMANDS_SUBMODULES`\n\n**Type:** `list[str]`\n\n**Default:** `[]`\n\nDefines submodules within app packages where commands should be discovered. Django's\ndefault `management.commands` is automatically inserted at index 0 if not explicitly\nincluded.\n\nExample:\n\n```python\nMANAGEMENT_COMMANDS_SUBMODULES = [\n    \"commands\",\n]\n```\n\nThis allows the utility to search for `Command` classes in both `myapp.management.commands.command`\nand `myapp.commands.command` for an app installed from the `myapp` module.\n\n**Important Notes:**\n\n- Items must be valid absolute dotted Python paths (although at runtime, they are\n  treated as relative paths appended to app names).\n\n#### `MANAGEMENT_COMMANDS_ALIASES`\n\n**Type:** `dict[str, list[str]]`\n\n**Default:** `{}`\n\nAllows the definition of shortcuts or aliases for sequences of Django commands.\n\nExample:\n\n```python\nMANAGEMENT_COMMANDS_ALIASES = {\n    \"full-check\": [\n        \"check --fail-level ERROR --deploy\",\n        \"makemigrations --check --dry-run --no-input\",\n        \"migrate --no-input\",\n    ],\n}\n```\n\nYou can now execute all the commands aliased by `full-check` with a single command:\n\n```console\npython manage.py full-check\n```\n\nAliases can refer to commands defined in the `MANAGEMENT_COMMANDS_PATHS` setting\nor other aliases.\n\n**Important Notes:**\n\n- Keys must be valid Python identifiers (with hyphens allowed).\n- Values should be command expressions with parsable arguments and options.\n- Circular references within aliases are not allowed, as they lead to infinite recursion.\n\n### Error Handling\n\n#### Configuration Checks\n\nThe plugin performs basic validation of user settings, primarily checking command\nnames, aliases, and module paths. If any checks fail, the plugin raises an `ImproperlyConfigured`\nerror.\n\nFor more information, see the `management_commands.conf` module.\n\n> The `ImproperlyConfigured` error here is distinct from the one in `django.core.exceptions`;\n> the plugin's uses its own exception class defined with its configuration.\n\n#### Custom Exceptions\n\nThe package includes custom exceptions for error handling:\n\n- **`CommandImportError`**: raised if the command class import fails;\n\n- **`CommandTypeError`**: raised if the imported command class is not a subclass\n  of Django's `BaseCommand`;\n\n- **`CommandClassLookupError`**: raised if a command cannot be discovered;\n\n- **`CommandAppLookupError`**: raised when a command is referenced by app label,\n  but the app with that label is not installed.\n\nFor more information, see the `management_commands.exceptions` module.\n\n> Be sure to review these exceptions when debugging or reporting issues.\n\n## Contributing\n\n- This is an open-source project and welcomes all types of contributions.\n- Contributors must adhere to our [Code of Conduct][code-of-conduct].\n- For detailed contribution guidelines, please refer to our [Contributing Guide][contributing].\n\n## License\n\nReleased under the [MIT license][license].\n\n[ci]: https://github.com/paduszyk/django-management-commands/actions/workflows/package-ci.yml\n[code-of-conduct]: https://github.com/paduszyk/django-management-commands/blob/main/docs/CODE_OF_CONDUCT.md\n[codecov]: https://app.codecov.io/gh/paduszyk/django-management-commands\n[contributing]: https://github.com/paduszyk/django-management-commands/blob/main/docs/CONTRIBUTING.md\n[conventional-commits]: https://www.conventionalcommits.org/\n[django-appconf]: https://github.com/django-compressor/django-appconf\n[django-commands]: https://docs.djangoproject.com/en/dev/howto/custom-management-commands/\n[license]: https://github.com/paduszyk/django-management-commands/blob/main/LICENSE\n[mypy]: https://mypy.readthedocs.io\n[nox]: https://nox.thea.codes/\n[pre-commit.ci]: https://results.pre-commit.ci/latest/github/paduszyk/django-management-commands/main\n[prettier]: https://prettier.io\n[pypi]: https://pypi.org/project/django-management-commands/\n[ruff]: https://docs.astral.sh/ruff/\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Modular discovery, aliasing, and sequencing of Django commands",
    "version": "1.1.0",
    "project_urls": {
        "Source": "https://github.com/paduszyk/django-management-commands"
    },
    "split_keywords": [
        "django",
        " django-application",
        " django-commands",
        " django-management-commands"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a1fe8aa83cec70519274be3fa81a050fdf674a255009d8cb883f9ecbbdff5ad0",
                "md5": "7f8ea1ed35267a6a058d9b5ebb1abe48",
                "sha256": "bf97d306b0a2f1473ba15e17b9c0e26d49e2b3336a143731e58d8190794ab903"
            },
            "downloads": -1,
            "filename": "django_management_commands-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7f8ea1ed35267a6a058d9b5ebb1abe48",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 10659,
            "upload_time": "2024-09-25T09:31:28",
            "upload_time_iso_8601": "2024-09-25T09:31:28.161283Z",
            "url": "https://files.pythonhosted.org/packages/a1/fe/8aa83cec70519274be3fa81a050fdf674a255009d8cb883f9ecbbdff5ad0/django_management_commands-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "13784f199fbbde6a7d114238297fe3a7fafcbfb593514b5b53271a268dce1fe0",
                "md5": "64a9190ab744e808dc22a4a26b78bdb4",
                "sha256": "5ac00f6c914d0e8659c6d24dbe0068a9070ca412e1dc62791f5c14d121ab9ab7"
            },
            "downloads": -1,
            "filename": "django_management_commands-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "64a9190ab744e808dc22a4a26b78bdb4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 12798,
            "upload_time": "2024-09-25T09:31:29",
            "upload_time_iso_8601": "2024-09-25T09:31:29.846033Z",
            "url": "https://files.pythonhosted.org/packages/13/78/4f199fbbde6a7d114238297fe3a7fafcbfb593514b5b53271a268dce1fe0/django_management_commands-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-25 09:31:29",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "paduszyk",
    "github_project": "django-management-commands",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-management-commands"
}
        
Elapsed time: 1.21983s