About Questionary Library for Settings Selection

If you have multiple settings files for your different environments, you can use the questionary library to let the developer select the appropriate settings file by arrow keys. Install questionary via pip:

(.venv)$ pip install questionary

Then modify your manage.py file:

#!/usr/bin/env python
import os
import sys
from pathlib import Path


def discover_settings_modules():
    settings_dir = Path(__file__).resolve().parent / "djangotricks" / "settings"
    return sorted(
        f"djangotricks.settings.{p.stem}"
        for p in settings_dir.glob("*.py")
        if not p.stem.startswith("_")
    )


def _settings_from_argv():
    """Return the value of --settings from sys.argv, or None."""
    import argparse

    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("--settings", default=None)
    args, _ = parser.parse_known_args()
    return args.settings


def select_settings():
    """Prompt the user to choose a settings module when running interactively."""
    cli_settings = _settings_from_argv()
    if cli_settings:
        os.environ["DJANGO_SETTINGS_MODULE"] = cli_settings
        return

    if "DJANGO_SETTINGS_MODULE" in os.environ:
        return

    # Non-interactive environments (e.g. CI, pipes) skip the prompt.
    if not sys.stdin.isatty():
        return

    import questionary

    modules = discover_settings_modules()
    if not modules:
        return

    choice = questionary.select(
        "Select settings module:",
        choices=modules,
    ).ask()

    if choice is None:
        # User cancelled (Ctrl-C / Ctrl-D).
        sys.exit(1)

    os.environ["DJANGO_SETTINGS_MODULE"] = choice


if __name__ == "__main__":
    select_settings()

    try:
        from django.core.management import execute_from_command_line
    except ImportError:
        try:
            import django  # noqa: F401
        except ImportError:
            raise ImportError(
                "Couldn't import Django. Are you sure it's installed and "
                "available on your PYTHONPATH environment variable? Did you "
                "forget to activate a virtual environment?"
            )
        raise
    execute_from_command_line(sys.argv)

The script assumes this file structure:

djangotricks/
├── __init__.py
└── settings/
    ├── __init__.py
    ├── _base.py
    ├── dev.py
    ├── test.py
    ├── staging.py
    └── production.py

And will give you choices like:

(.venv)$ python manage.py shell
? Select settings module: (Use arrow keys)
 » djangotricks.settings.dev
   djangotricks.settings.production
   djangotricks.settings.staging
   djangotricks.settings.test

Tips and Tricks Dev Ops Developer Experience Django 6.x Django 5.2 Django 4.2 Python 3 questionary