Combine multiple `shell` commands across apps using `get_auto_imports`?

Django 5.2 introduced the ability to customize the shell management command by overriding the get_auto_imports() method in a management command subclass (see the release note or this page of the doc).

That's a nice feature and it works well for a single app, but I'm running into trouble trying to make it scale across multiple apps.

For instance, in app1/management/commands/shell.py:

from django.core.management.commands import shell

class Command(shell.Command):
    def get_auto_imports(self) -> list[str]:
        return [
            *super().get_auto_imports(),
            "app1.module1",
        ]

And in app2/management/commands/shell.py:

from django.core.management.commands import shell

class Command(shell.Command):
    def get_auto_imports(self) -> list[str]:
        return [
            *super().get_auto_imports(),
            "app2.module2",
        ]

The issue is that only one of these is picked up by Django — whichever app comes first in INSTALLED_APPS. This seems to be by design, as Django only uses the first matching management command it finds.

Is there a clean way to combine auto imports from multiple apps or extend the shell command across apps without having to manually centralize everything in one location?

I’m looking for a generic and scalable solution that allows each app to contribute its own imports to the shell, ideally still using get_auto_imports() so the logic stays clean and encapsulated per app.

I don't think you need to define multiple shell commands, you can probably let every app say what should be autoimported.

So:

# app_1/apps.py

from django.apps import AppConfig


class App1Config(AppConfig):
    # ...
    shell_auto_imports = ('app1.module1',)

and:

# app_2/apps.py

from django.apps import AppConfig


class App2Config(AppConfig):
    # ...
    shell_auto_imports = ('app2.module2',)

and work with one shell script:

from django.apps import apps
from django.core.management.commands import shell

class Command(shell.Command):
    def get_auto_imports(self) -> list[str]:
        extras = [
            item
            for config in apps.get_app_configs()
            for item in getattr(config, 'shell_auto_imports', ())
        ]
        return [
            *super().get_auto_imports(),
            *extras
        ]

Вернуться на верх