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
]