Skip to content

spire_startapp_pkg

django_spire.core.management.commands.spire_startapp_pkg

__all__ = ['AppConfig', 'AppConfigFactory', 'AppGenerator', 'AppRegistry', 'AppValidator', 'FileSystem', 'PathConfig', 'PathResolver', 'PermissionInheritanceHandler', 'Reporter', 'TemplateBuilder', 'TemplateEngine', 'TemplateGenerator', 'TemplateProcessor', 'UserInputCollector', 'generate_replacement_map'] module-attribute

TemplateBuilder

Builds and displays tree structures for app and template creation.

This class generates visual representations of the file structure that will be created for new apps and their associated templates.

Initializes the TemplateBuilder with a reporter for output.

Parameters:

  • reporter (Reporter) –

    Reporter instance for displaying output to the user.

Source code in django_spire/core/management/commands/spire_startapp_pkg/builder.py
def __init__(self, reporter: Reporter):
    """
    Initializes the TemplateBuilder with a reporter for output.

    :param reporter: Reporter instance for displaying output to the user.
    """

    self._reporter = reporter

build_app_tree_structure

Displays a tree structure of the app files that will be created.

This method shows the user what Python files, directories, and modules will be generated for the new Django app before creation.

Parameters:

  • base (Path) –

    Base directory where the app will be created.

  • components (list[str]) –

    List of app path components (e.g., ['app', 'human_resource', 'employee']).

  • registry (list[str]) –

    List of already registered apps in the Django project.

  • template (Path) –

    Path to the app template directory.

Source code in django_spire/core/management/commands/spire_startapp_pkg/builder.py
def build_app_tree_structure(
    self,
    base: Path,
    components: list[str],
    registry: list[str],
    template: Path
) -> None:
    """
    Displays a tree structure of the app files that will be created.

    This method shows the user what Python files, directories, and modules
    will be generated for the new Django app before creation.

    :param base: Base directory where the app will be created.
    :param components: List of app path components (e.g., ['app', 'human_resource', 'employee']).
    :param registry: List of already registered apps in the Django project.
    :param template: Path to the app template directory.
    """

    self._reporter.report_tree_structure(
        title='\nThe following app(s) will be created:\n\n',
        base=base,
        components=components,
        registry=registry,
        template=template,
        formatter=self._reporter.format_app_item,
        transformation=self._reporter.transform_app_component,
    )

build_html_tree_structure

Displays a tree structure of the HTML template files that will be created.

This method shows the user what HTML templates, cards, forms, and pages will be generated for the new Django app before creation.

Parameters:

  • base (Path) –

    Base directory where templates will be created.

  • components (list[str]) –

    List of app path components.

  • registry (list[str]) –

    List of already registered apps in the Django project.

  • template (Path) –

    Path to the HTML template directory.

Source code in django_spire/core/management/commands/spire_startapp_pkg/builder.py
def build_html_tree_structure(
    self,
    base: Path,
    components: list[str],
    registry: list[str],
    template: Path
) -> None:
    """
    Displays a tree structure of the HTML template files that will be created.

    This method shows the user what HTML templates, cards, forms, and pages
    will be generated for the new Django app before creation.

    :param base: Base directory where templates will be created.
    :param components: List of app path components.
    :param registry: List of already registered apps in the Django project.
    :param template: Path to the HTML template directory.
    """

    replacement = generate_replacement_map(components)

    def html_formatter_with_replacement(item: Path) -> str:
        return self._reporter.format_html_item(item, replacement)

    self._reporter.report_tree_structure(
        title='\nThe following template(s) will be created:\n\n',
        base=base,
        components=components,
        registry=registry,
        template=template,
        formatter=html_formatter_with_replacement,
        transformation=self._reporter.transform_html_component,
    )

AppConfig dataclass

Configuration for a new Django app being created.

This class contains all the information needed to generate a new app, including its name, path, components, destinations, and user-provided inputs.

app_name instance-attribute

app_path instance-attribute

components instance-attribute

destination instance-attribute

template_destination instance-attribute

user_inputs instance-attribute

app_label property

Gets the Django app label.

Returns:

  • str

    The app label, either from user input or derived from app name.

model_name property

Gets the model class name.

Returns:

  • str

    The model name, either from user input or TitleCase version of app name.

AppConfigFactory

Factory class for creating AppConfig instances.

This class handles the creation of AppConfig objects by resolving paths and processing user inputs.

Initializes the factory with a path resolver.

Parameters:

  • path_resolver (PathResolver) –

    Path resolver for determining file system locations.

Source code in django_spire/core/management/commands/spire_startapp_pkg/config.py
def __init__(self, path_resolver: PathResolver):
    """
    Initializes the factory with a path resolver.

    :param path_resolver: Path resolver for determining file system locations.
    """

    self._path_resolver = path_resolver

create_config

Creates an AppConfig from an app path and user inputs.

Parameters:

  • app_path (str) –

    Dot-separated app path (e.g., 'app.human_resource.employee').

  • user_inputs (dict[str, str]) –

    Dictionary of user-provided configuration values.

Returns:

  • AppConfig

    Configured AppConfig instance ready for app generation.

Source code in django_spire/core/management/commands/spire_startapp_pkg/config.py
def create_config(self, app_path: str, user_inputs: dict[str, str]) -> AppConfig:
    """
    Creates an AppConfig from an app path and user inputs.

    :param app_path: Dot-separated app path (e.g., 'app.human_resource.employee').
    :param user_inputs: Dictionary of user-provided configuration values.
    :return: Configured AppConfig instance ready for app generation.
    """

    components = app_path.split('.')
    app_name = user_inputs.get('app_name', components[-1])

    return AppConfig(
        app_name=app_name,
        app_path=app_path,
        components=components,
        destination=self._path_resolver.get_app_destination(components),
        template_destination=self._path_resolver.get_template_destination(components),
        user_inputs=user_inputs
    )

PathConfig dataclass

Configuration for template directory paths.

This class holds the paths to the app and HTML template directories used for generating new Django apps.

app_template instance-attribute

html_template instance-attribute

default classmethod

Creates a default PathConfig with standard template locations.

Returns:

  • PathConfig

    PathConfig instance with paths to default app and HTML templates.

Source code in django_spire/core/management/commands/spire_startapp_pkg/config.py
@classmethod
def default(cls) -> PathConfig:
    """
    Creates a default PathConfig with standard template locations.

    :return: PathConfig instance with paths to default app and HTML templates.
    """

    base = Path(django_spire.__file__).parent

    return cls(
        app_template=base / 'core/management/commands/spire_startapp_pkg/template/app',
        html_template=base / 'core/management/commands/spire_startapp_pkg/template/templates'
    )

FileSystem

Implementation of file system operations for app generation.

This class provides concrete implementations of file system operations needed to create directories, copy templates, and manage files.

copy_tree

Copies an entire directory tree from source to destination.

Ignores Python cache directories and compiled files during the copy.

Parameters:

  • src (Path) –

    Source directory path to copy from.

  • dst (Path) –

    Destination directory path to copy to.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def copy_tree(self, src: Path, dst: Path) -> None:
    """
    Copies an entire directory tree from source to destination.

    Ignores Python cache directories and compiled files during the copy.

    :param src: Source directory path to copy from.
    :param dst: Destination directory path to copy to.
    """

    shutil.copytree(
        src,
        dst,
        dirs_exist_ok=True,
        ignore=shutil.ignore_patterns('__pycache__', '*.pyc')
    )

create_directory

Creates a directory and all necessary parent directories.

Parameters:

  • path (Path) –

    Directory path to create.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def create_directory(self, path: Path) -> None:
    """
    Creates a directory and all necessary parent directories.

    :param path: Directory path to create.
    """

    path.mkdir(parents=True, exist_ok=True)

exists

Checks if a path exists on the file system.

Parameters:

  • path (Path) –

    Path to check for existence.

Returns:

  • bool

    True if the path exists, False otherwise.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def exists(self, path: Path) -> bool:
    """
    Checks if a path exists on the file system.

    :param path: Path to check for existence.
    :return: True if the path exists, False otherwise.
    """

    return path.exists()

has_content

Checks if a directory exists and contains any files or subdirectories.

Parameters:

  • path (Path) –

    Directory path to check.

Returns:

  • bool

    True if the directory exists and has content, False otherwise.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def has_content(self, path: Path) -> bool:
    """
    Checks if a directory exists and contains any files or subdirectories.

    :param path: Directory path to check.
    :return: True if the directory exists and has content, False otherwise.
    """

    return self.exists(path) and any(path.iterdir())

iterate_files

Recursively finds all files matching a pattern in a directory.

Parameters:

  • path (Path) –

    Directory path to search within.

  • pattern (str) –

    Glob pattern to match files (e.g., '.py', '.template').

Returns:

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def iterate_files(self, path: Path, pattern: str) -> Iterator[Path]:
    """
    Recursively finds all files matching a pattern in a directory.

    :param path: Directory path to search within.
    :param pattern: Glob pattern to match files (e.g., '*.py', '*.template').
    :return: Iterator of matching file paths.
    """

    return path.rglob(pattern)

read_file

Reads the entire contents of a text file.

Parameters:

  • path (Path) –

    File path to read.

Returns:

  • str

    File contents as a string.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def read_file(self, path: Path) -> str:
    """
    Reads the entire contents of a text file.

    :param path: File path to read.
    :return: File contents as a string.
    """

    with open(path, 'r', encoding='utf-8') as handle:
        return handle.read()

rename

Renames a file or directory.

Parameters:

  • old (Path) –

    Current path of the file or directory.

  • new (Path) –

    New path for the file or directory.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def rename(self, old: Path, new: Path) -> None:
    """
    Renames a file or directory.

    :param old: Current path of the file or directory.
    :param new: New path for the file or directory.
    """

    old.rename(new)

write_file

Writes content to a text file.

Parameters:

  • path (Path) –

    File path to write to.

  • content (str) –

    String content to write to the file.

Source code in django_spire/core/management/commands/spire_startapp_pkg/filesystem.py
def write_file(self, path: Path, content: str) -> None:
    """
    Writes content to a text file.

    :param path: File path to write to.
    :param content: String content to write to the file.
    """

    with open(path, 'w', encoding='utf-8') as handle:
        handle.write(content)

AppGenerator

Generates Django app structures from templates.

This class handles the creation of new Django apps by copying template files and processing them with user-provided configuration.

Initializes the AppGenerator with required dependencies.

Parameters:

  • filesystem (FileSystem) –

    File system for file operations.

  • processor (TemplateProcessor) –

    Template processor for replacing placeholders.

  • reporter (Reporter) –

    Reporter for user feedback and output.

  • path_config (PathConfig) –

    Configuration containing template paths.

Source code in django_spire/core/management/commands/spire_startapp_pkg/generator.py
def __init__(
    self,
    filesystem: FileSystem,
    processor: TemplateProcessor,
    reporter: Reporter,
    path_config: PathConfig
):
    """
    Initializes the AppGenerator with required dependencies.

    :param filesystem: File system for file operations.
    :param processor: Template processor for replacing placeholders.
    :param reporter: Reporter for user feedback and output.
    :param path_config: Configuration containing template paths.
    """

    self._filesystem = filesystem
    self._path_config = path_config
    self._processor = processor
    self._reporter = reporter

generate

Generates a new Django app from templates.

Creates the app directory, copies template files, and processes them with user configuration. Skips generation if the app already exists.

Parameters:

  • config (AppConfig) –

    Configuration for the app to generate.

Source code in django_spire/core/management/commands/spire_startapp_pkg/generator.py
def generate(self, config: AppConfig) -> None:
    """
    Generates a new Django app from templates.

    Creates the app directory, copies template files, and processes
    them with user configuration. Skips generation if the app already exists.

    :param config: Configuration for the app to generate.
    """

    if self._filesystem.has_content(config.destination):
        self._reporter.report_app_exists(config.app_path, config.destination)
        return

    self._validate_template_exists(self._path_config.app_template, 'app template')
    self._reporter.report_creating_app(config.app_path, config.destination)

    self._filesystem.create_directory(config.destination)
    self._filesystem.copy_tree(self._path_config.app_template, config.destination)

    self._processor.process_app_templates(
        config.destination,
        config.components,
        config.user_inputs
    )

    self._reporter.report_app_creation_success(config.app_path)

TemplateGenerator

Generates HTML templates for Django apps.

This class handles the creation of HTML template files including forms, cards, pages, and items for new Django apps.

Initializes the TemplateGenerator with required dependencies.

Parameters:

  • filesystem (FileSystem) –

    File system for file operations.

  • processor (TemplateProcessor) –

    Template processor for replacing placeholders.

  • reporter (Reporter) –

    Reporter for user feedback and output.

  • path_config (PathConfig) –

    Configuration containing template paths.

Source code in django_spire/core/management/commands/spire_startapp_pkg/generator.py
def __init__(
    self,
    filesystem: FileSystem,
    processor: TemplateProcessor,
    reporter: Reporter,
    path_config: PathConfig
):
    """
    Initializes the TemplateGenerator with required dependencies.

    :param filesystem: File system for file operations.
    :param processor: Template processor for replacing placeholders.
    :param reporter: Reporter for user feedback and output.
    :param path_config: Configuration containing template paths.
    """

    self._filesystem = filesystem
    self._path_config = path_config
    self._processor = processor
    self._reporter = reporter

generate

Generates HTML templates for a new Django app.

Creates the template directory, copies template files, and processes them with user configuration. Skips generation if templates already exist.

Parameters:

  • config (AppConfig) –

    Configuration for the templates to generate.

Source code in django_spire/core/management/commands/spire_startapp_pkg/generator.py
def generate(self, config: AppConfig) -> None:
    """
    Generates HTML templates for a new Django app.

    Creates the template directory, copies template files, and processes
    them with user configuration. Skips generation if templates already exist.

    :param config: Configuration for the templates to generate.
    """

    if self._filesystem.has_content(config.template_destination):
        self._reporter.report_templates_exist(config.app_path, config.template_destination)
        return

    self._validate_template_exists(self._path_config.html_template, 'templates template')
    self._reporter.report_creating_templates(config.app_path, config.template_destination)

    self._filesystem.create_directory(config.template_destination)
    self._filesystem.copy_tree(self._path_config.html_template, config.template_destination)

    self._processor.process_html_templates(
        config.template_destination,
        config.components,
        config.user_inputs
    )

    self._reporter.report_templates_creation_success(config.app_path)

PermissionInheritanceHandler

Handles permission inheritance configuration for nested Django apps.

This class manages the interactive collection of permission inheritance settings when creating child apps that may inherit permissions from parent apps.

Initializes the handler with a reporter for user interaction.

Parameters:

  • reporter (Reporter) –

    Reporter instance for displaying prompts and messages.

Source code in django_spire/core/management/commands/spire_startapp_pkg/permissions.py
def __init__(self, reporter: Reporter):
    """
    Initializes the handler with a reporter for user interaction.

    :param reporter: Reporter instance for displaying prompts and messages.
    """

    self.reporter = reporter

reporter = reporter instance-attribute

collect_inheritance_data

Collects permission inheritance configuration from the user.

Prompts the user to determine if the new app should inherit permissions from its parent app, and if so, collects the necessary parent model information.

Parameters:

  • components (list[str]) –

    List of app path components.

Returns:

  • dict[str, Any]

    Dictionary containing inheritance configuration data.

Source code in django_spire/core/management/commands/spire_startapp_pkg/permissions.py
def collect_inheritance_data(self, components: list[str]) -> dict[str, Any]:
    """
    Collects permission inheritance configuration from the user.

    Prompts the user to determine if the new app should inherit permissions
    from its parent app, and if so, collects the necessary parent model information.

    :param components: List of app path components.
    :return: Dictionary containing inheritance configuration data.
    """

    if len(components) <= 2:
        return {
            'inherit_permissions': False,
            'parent_model_instance_name': '',
            'parent_permission_prefix': '',
        }

    if not self._should_inherit_permissions():
        return {
            'inherit_permissions': False,
            'parent_model_instance_name': '',
            'parent_permission_prefix': '',
        }

    return {
        'inherit_permissions': True,
        'parent_model_instance_name': self._collect_parent_model_instance_name(components),
        'parent_model_path': self._collect_parent_model_path(components),
        'parent_permission_prefix': self._collect_parent_permission_prefix(components),
    }

TemplateEngine

Renders template strings with variable replacements.

This class uses Python's string.Template to safely substitute placeholders in template files with actual values.

render

Renders a template string by replacing placeholders with values.

Parameters:

  • text (str) –

    Template string containing ${variable} placeholders.

  • replacements (dict[str, str]) –

    Dictionary mapping placeholder names to their values.

Returns:

  • str

    Rendered string with all placeholders replaced.

Source code in django_spire/core/management/commands/spire_startapp_pkg/processor.py
def render(self, text: str, replacements: dict[str, str]) -> str:
    """
    Renders a template string by replacing placeholders with values.

    :param text: Template string containing ${variable} placeholders.
    :param replacements: Dictionary mapping placeholder names to their values.
    :return: Rendered string with all placeholders replaced.
    """

    template = Template(text)
    return template.safe_substitute(replacements)

TemplateProcessor

Processes template files for Django app generation.

This class handles the replacement of placeholders in template files and manages file renaming based on user configuration.

Initializes the processor with an engine and file system.

Parameters:

  • engine (TemplateEngine) –

    Template engine for rendering strings.

  • filesystem (FileSystem) –

    File system for file operations.

Source code in django_spire/core/management/commands/spire_startapp_pkg/processor.py
def __init__(self, engine: TemplateEngine, filesystem: FileSystem):
    """
    Initializes the processor with an engine and file system.

    :param engine: Template engine for rendering strings.
    :param filesystem: File system for file operations.
    """

    self._engine = engine
    self._filesystem = filesystem

process_app_templates

Processes all template files in an app directory.

Replaces placeholders in .template files, renames them, and updates content in .py files based on user inputs.

Parameters:

  • directory (Path) –

    Root directory containing template files.

  • components (list[str]) –

    List of app path components.

  • user_inputs (dict[str, str] | None, default: None ) –

    Optional dictionary of user-provided configuration values.

Source code in django_spire/core/management/commands/spire_startapp_pkg/processor.py
def process_app_templates(
    self,
    directory: Path,
    components: list[str],
    user_inputs: dict[str, str] | None = None
) -> None:
    """
    Processes all template files in an app directory.

    Replaces placeholders in .template files, renames them, and updates
    content in .py files based on user inputs.

    :param directory: Root directory containing template files.
    :param components: List of app path components.
    :param user_inputs: Optional dictionary of user-provided configuration values.
    """

    for file_path in self._filesystem.iterate_files(directory, '*.template'):
        self._process_file(file_path, components, user_inputs)

    for file_path in self._filesystem.iterate_files(directory, '*.py'):
        self._replace_content(file_path, components, user_inputs)
        self._rename_file(file_path, components, user_inputs)

    self._rename_template_files(directory)

process_html_templates

Processes all HTML template files in a directory.

Replaces placeholders in .template files and renames them to remove the .template extension.

Parameters:

  • directory (Path) –

    Root directory containing HTML template files.

  • components (list[str]) –

    List of app path components.

  • user_inputs (dict[str, str] | None, default: None ) –

    Optional dictionary of user-provided configuration values.

Source code in django_spire/core/management/commands/spire_startapp_pkg/processor.py
def process_html_templates(
    self,
    directory: Path,
    components: list[str],
    user_inputs: dict[str, str] | None = None
) -> None:
    """
    Processes all HTML template files in a directory.

    Replaces placeholders in .template files and renames them to remove
    the .template extension.

    :param directory: Root directory containing HTML template files.
    :param components: List of app path components.
    :param user_inputs: Optional dictionary of user-provided configuration values.
    """

    for file_path in self._filesystem.iterate_files(directory, '*.template'):
        self._process_file(file_path, components, user_inputs)

    self._rename_template_files(directory)

AppRegistry

Manages Django app registration information.

This class provides methods to query which apps are installed in the Django project and validate app component hierarchies.

get_installed_apps

Gets a list of all installed app names.

Returns:

  • list[str]

    List of fully qualified app names from Django's app registry.

Source code in django_spire/core/management/commands/spire_startapp_pkg/registry.py
def get_installed_apps(self) -> list[str]:
    """
    Gets a list of all installed app names.

    :return: List of fully qualified app names from Django's app registry.
    """

    return [config.name for config in apps.get_app_configs()]

get_missing_components

Identifies which app components in a path are not registered.

For a path like ['app', 'human_resource', 'employee'], this checks if 'app', 'app.human_resource', and 'app.human_resource.employee' are registered, and returns those that are missing.

Parameters:

  • components (list[str]) –

    List of app path components to check.

Returns:

  • list[str]

    List of unregistered component paths.

Source code in django_spire/core/management/commands/spire_startapp_pkg/registry.py
def get_missing_components(self, components: list[str]) -> list[str]:
    """
    Identifies which app components in a path are not registered.

    For a path like ['app', 'human_resource', 'employee'], this checks
    if 'app', 'app.human_resource', and 'app.human_resource.employee'
    are registered, and returns those that are missing.

    :param components: List of app path components to check.
    :return: List of unregistered component paths.
    """

    registry = self.get_installed_apps()
    missing = []

    total = len(components)

    for i in range(total):
        component = '.'.join(components[: i + 1])

        if component not in registry and i > 0:
            missing.append(component)

    return missing

get_valid_root_apps

Gets all valid root app names from INSTALLED_APPS.

Returns root-level apps (first component before a dot) that can be used as parent apps, excluding Django's built-in apps.

Returns:

  • set[str]

    Set of valid root app names.

Source code in django_spire/core/management/commands/spire_startapp_pkg/registry.py
def get_valid_root_apps(self) -> set[str]:
    """
    Gets all valid root app names from INSTALLED_APPS.

    Returns root-level apps (first component before a dot) that can be
    used as parent apps, excluding Django's built-in apps.

    :return: Set of valid root app names.
    """

    return {
        app.split('.')[0]
        for app in settings.INSTALLED_APPS
        if '.' in app and app.split('.')[0] != 'django'
    }

is_app_registered

Checks if an app path is registered in Django.

Parameters:

  • app_path (str) –

    Dot-separated app path to check.

Returns:

  • bool

    True if the app is registered, False otherwise.

Source code in django_spire/core/management/commands/spire_startapp_pkg/registry.py
def is_app_registered(self, app_path: str) -> bool:
    """
    Checks if an app path is registered in Django.

    :param app_path: Dot-separated app path to check.
    :return: True if the app is registered, False otherwise.
    """

    return app_path in self.get_installed_apps()

Reporter

Handles user interaction and console output for the app creation command.

This class manages all console output including status messages, tree structures, confirmations, and styled text for the app creation process.

Initializes the reporter with a Django management command.

Parameters:

  • command (BaseCommand) –

    Django BaseCommand instance for accessing stdout and styling.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def __init__(self, command: BaseCommand):
    """
    Initializes the reporter with a Django management command.

    :param command: Django BaseCommand instance for accessing stdout and styling.
    """

    self.command = command
    self.style_error = command.style.ERROR
    self.style_notice = command.style.NOTICE
    self.style_success = command.style.SUCCESS
    self.style_warning = command.style.WARNING

ICON_FILE = '📄' class-attribute instance-attribute

ICON_FOLDER_CLOSED = '📁' class-attribute instance-attribute

ICON_FOLDER_OPEN = '📂' class-attribute instance-attribute

INDENTATION = ' ' class-attribute instance-attribute

command = command instance-attribute

style_error = command.style.ERROR instance-attribute

style_notice = command.style.NOTICE instance-attribute

style_success = command.style.SUCCESS instance-attribute

style_warning = command.style.WARNING instance-attribute

format_app_item

Formats an app file or directory name for display.

Removes the .template extension from Python files.

Parameters:

  • item (Path) –

    Path to the item to format.

Returns:

  • str

    Formatted item name.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def format_app_item(self, item: Path) -> str:
    """
    Formats an app file or directory name for display.

    Removes the .template extension from Python files.

    :param item: Path to the item to format.
    :return: Formatted item name.
    """

    return item.name.replace('.py.template', '.py')

format_html_item

Formats an HTML template file or directory name for display.

Applies variable replacements and removes .template extensions.

Parameters:

  • item (Path) –

    Path to the item to format.

  • replacement (dict[str, str]) –

    Dictionary of placeholder replacements.

Returns:

  • str

    Formatted item name with placeholders replaced.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def format_html_item(self, item: Path, replacement: dict[str, str]) -> str:
    """
    Formats an HTML template file or directory name for display.

    Applies variable replacements and removes .template extensions.

    :param item: Path to the item to format.
    :param replacement: Dictionary of placeholder replacements.
    :return: Formatted item name with placeholders replaced.
    """

    if item.is_dir():
        return item.name

    template = Template(item.name)
    filename = template.safe_substitute(replacement)

    if filename.endswith('.template'):
        filename = filename.replace('.template', '')

    return filename

prompt_confirmation

Prompts the user for yes/no confirmation.

Parameters:

  • message (str) –

    Confirmation prompt message.

Returns:

  • bool

    True if user responds with 'y', False otherwise.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def prompt_confirmation(self, message: str) -> bool:
    """
    Prompts the user for yes/no confirmation.

    :param message: Confirmation prompt message.
    :return: True if user responds with 'y', False otherwise.
    """

    return input(message).strip().lower() == 'y'

report_app_creation_success

Reports successful creation of an app.

Parameters:

  • app (str) –

    Name of the app that was created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_app_creation_success(self, app: str) -> None:
    """
    Reports successful creation of an app.

    :param app: Name of the app that was created.
    """

    self.write(f'Successfully created app: {app}', self.style_success)

report_app_exists

Reports that an app already exists at the destination.

Parameters:

  • app (str) –

    Name of the app.

  • destination (Path) –

    Path where the app already exists.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_app_exists(self, app: str, destination: Path) -> None:
    """
    Reports that an app already exists at the destination.

    :param app: Name of the app.
    :param destination: Path where the app already exists.
    """

    self.write(f'The app "{app}" already exists at {destination}', self.style_warning)

report_creating_app

Reports that an app is being created.

Parameters:

  • app (str) –

    Name of the app being created.

  • destination (Path) –

    Path where the app will be created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_creating_app(self, app: str, destination: Path) -> None:
    """
    Reports that an app is being created.

    :param app: Name of the app being created.
    :param destination: Path where the app will be created.
    """

    self.write(f'Creating app "{app}" at {destination}', self.style_notice)

report_creating_templates

Reports that templates are being created for an app.

Parameters:

  • app (str) –

    Name of the app.

  • destination (Path) –

    Path where templates will be created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_creating_templates(self, app: str, destination: Path) -> None:
    """
    Reports that templates are being created for an app.

    :param app: Name of the app.
    :param destination: Path where templates will be created.
    """

    self.write(f'Creating templates for app "{app}" at {destination}', self.style_notice)

report_installed_apps_suggestion

Suggests which app to add to INSTALLED_APPS in settings.py.

Parameters:

  • missing_components (list[str]) –

    List of missing app components.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_installed_apps_suggestion(self, missing_components: list[str]) -> None:
    """
    Suggests which app to add to INSTALLED_APPS in settings.py.

    :param missing_components: List of missing app components.
    """

    self.write('\nPlease add the following to INSTALLED_APPS in settings.py:', self.style_notice)
    self.write(f'\n {missing_components[-1]}', lambda x: x)

report_missing_components

Reports which app components are not yet registered.

Parameters:

  • missing_components (list[str]) –

    List of unregistered app component paths.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_missing_components(self, missing_components: list[str]) -> None:
    """
    Reports which app components are not yet registered.

    :param missing_components: List of unregistered app component paths.
    """

    self.write('The following are not registered apps:', self.style_warning)
    self.write('\n'.join(f' - {app}' for app in missing_components), lambda x: x)

report_templates_creation_success

Reports successful creation of templates for an app.

Parameters:

  • app (str) –

    Name of the app whose templates were created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_templates_creation_success(self, app: str) -> None:
    """
    Reports successful creation of templates for an app.

    :param app: Name of the app whose templates were created.
    """

    self.write(f'Successfully created templates for app: {app}', self.style_success)

report_templates_exist

Reports that templates already exist for an app.

Parameters:

  • app (str) –

    Name of the app.

  • destination (Path) –

    Path where templates already exist.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_templates_exist(self, app: str, destination: Path) -> None:
    """
    Reports that templates already exist for an app.

    :param app: Name of the app.
    :param destination: Path where templates already exist.
    """

    self.write(f'The templates for app "{app}" already exist at {destination}', self.style_warning)

report_tree_structure

Displays a tree structure of files and directories that will be created.

Shows a hierarchical view of the app structure with appropriate icons and formatting for files and directories.

Parameters:

  • title (str) –

    Title to display above the tree structure.

  • base (Path) –

    Base directory path.

  • components (list[str]) –

    List of app path components.

  • registry (list[str]) –

    List of registered apps.

  • template (Path) –

    Path to template directory.

  • formatter (Callable[[Path], str]) –

    Function to format item names for display.

  • transformation (Callable[[int, str], str] | None, default: None ) –

    Optional function to transform component names.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def report_tree_structure(
    self,
    title: str,
    base: Path,
    components: list[str],
    registry: list[str],
    template: Path,
    formatter: Callable[[Path], str],
    transformation: Callable[[int, str], str] | None = None,
) -> None:
    """
    Displays a tree structure of files and directories that will be created.

    Shows a hierarchical view of the app structure with appropriate icons
    and formatting for files and directories.

    :param title: Title to display above the tree structure.
    :param base: Base directory path.
    :param components: List of app path components.
    :param registry: List of registered apps.
    :param template: Path to template directory.
    :param formatter: Function to format item names for display.
    :param transformation: Optional function to transform component names.
    """

    if transformation is None:
        transformation = self.transform_app_component

    self.command.stdout.write(title)
    current = base

    for i, component in enumerate(components):
        latest = components[: i + 1]
        replacement = generate_replacement_map(latest)

        component = transformation(i, component)
        current = current / component
        app = '.'.join(latest)
        indent = self.INDENTATION * i

        self.command.stdout.write(f'{indent}{self.ICON_FOLDER_OPEN} {component}/')

        if i == len(components) - 1 and app not in registry and template.exists():
            def local_formatter(item: Path, mapping: dict[str, str] = replacement) -> str:
                base_name = formatter(item)
                return self._apply_replacement(base_name, mapping)

            self._show_tree_from_template(template, indent + self.INDENTATION, local_formatter)

transform_app_component

Transforms an app component name (default: no transformation).

Parameters:

  • _index (int) –

    Index of the component in the path.

  • component (str) –

    Component name to transform.

Returns:

  • str

    Transformed component name.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def transform_app_component(self, _index: int, component: str) -> str:
    """
    Transforms an app component name (default: no transformation).

    :param _index: Index of the component in the path.
    :param component: Component name to transform.
    :return: Transformed component name.
    """

    return component

transform_html_component

Transforms an HTML component name (replaces first component with 'templates').

Parameters:

  • index (int) –

    Index of the component in the path.

  • component (str) –

    Component name to transform.

Returns:

  • str

    Transformed component name.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def transform_html_component(self, index: int, component: str) -> str:
    """
    Transforms an HTML component name (replaces first component with 'templates').

    :param index: Index of the component in the path.
    :param component: Component name to transform.
    :return: Transformed component name.
    """

    return 'templates' if index == 0 else component

write

Writes a styled message to the console.

Parameters:

  • message (str) –

    Message to display.

  • style (Callable[[str], str]) –

    Styling function to apply to the message.

Source code in django_spire/core/management/commands/spire_startapp_pkg/reporter.py
def write(self, message: str, style: Callable[[str], str]) -> None:
    """
    Writes a styled message to the console.

    :param message: Message to display.
    :param style: Styling function to apply to the message.
    """

    self.command.stdout.write(style(message))

PathResolver

Resolves file system paths for app and template creation.

This class determines where new Django apps and their templates should be created based on project structure and configuration.

Initializes the path resolver with base directories.

Parameters:

  • base_dir (Path | None, default: None ) –

    Optional base directory for the Django project (defaults to settings.BASE_DIR).

  • template_dir (Path | None, default: None ) –

    Optional template directory (defaults to base_dir/templates).

Source code in django_spire/core/management/commands/spire_startapp_pkg/resolver.py
def __init__(self, base_dir: Path | None = None, template_dir: Path | None = None):
    """
    Initializes the path resolver with base directories.

    :param base_dir: Optional base directory for the Django project (defaults to settings.BASE_DIR).
    :param template_dir: Optional template directory (defaults to base_dir/templates).
    """

    self._base_dir = base_dir or Path(settings.BASE_DIR)
    self._template_dir = template_dir or self._base_dir / 'templates'

get_app_destination

Gets the destination path for a new app based on its components.

For components ['app', 'human_resource', 'employee'], returns Path('base_dir/app/human_resource/employee').

Parameters:

  • components (list[str]) –

    List of app path components.

Returns:

  • Path

    Full path where the app should be created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/resolver.py
def get_app_destination(self, components: list[str]) -> Path:
    """
    Gets the destination path for a new app based on its components.

    For components ['app', 'human_resource', 'employee'], returns
    Path('base_dir/app/human_resource/employee').

    :param components: List of app path components.
    :return: Full path where the app should be created.
    """

    return self._base_dir.joinpath(*components)

get_base_dir

Gets the project's base directory.

Returns:

  • Path

    Base directory path for the Django project.

Source code in django_spire/core/management/commands/spire_startapp_pkg/resolver.py
def get_base_dir(self) -> Path:
    """
    Gets the project's base directory.

    :return: Base directory path for the Django project.
    """

    return self._base_dir

get_template_destination

Gets the destination path for templates based on app components.

Excludes the first component (root app) from the path. For components ['app', 'human_resource', 'employee'], returns Path('templates/human_resource/employee').

Parameters:

  • components (list[str]) –

    List of app path components.

Returns:

  • Path

    Full path where templates should be created.

Source code in django_spire/core/management/commands/spire_startapp_pkg/resolver.py
def get_template_destination(self, components: list[str]) -> Path:
    """
    Gets the destination path for templates based on app components.

    Excludes the first component (root app) from the path. For components
    ['app', 'human_resource', 'employee'], returns
    Path('templates/human_resource/employee').

    :param components: List of app path components.
    :return: Full path where templates should be created.
    """

    template_components = components[1:] if len(components) > 1 else components
    return self._template_dir.joinpath(*template_components)

get_template_dir

Gets the project's template directory.

Returns:

  • Path

    Template directory path for the Django project.

Source code in django_spire/core/management/commands/spire_startapp_pkg/resolver.py
def get_template_dir(self) -> Path:
    """
    Gets the project's template directory.

    :return: Template directory path for the Django project.
    """

    return self._template_dir

UserInputCollector

Collects user input for Django app creation through an interactive wizard.

This class guides users through a step-by-step process to gather all necessary configuration for creating a new Django app.

Initializes the collector with a reporter and validator.

Parameters:

  • reporter (Reporter) –

    Reporter instance for displaying prompts and messages.

  • validator (AppValidator) –

    Validator for checking user input validity.

Source code in django_spire/core/management/commands/spire_startapp_pkg/user_input.py
def __init__(self, reporter: Reporter, validator: AppValidator):
    """
    Initializes the collector with a reporter and validator.

    :param reporter: Reporter instance for displaying prompts and messages.
    :param validator: Validator for checking user input validity.
    """

    self.reporter = reporter
    self.validator = validator

reporter = reporter instance-attribute

validator = validator instance-attribute

collect_all_inputs

Collects all required user inputs for app creation.

Guides the user through an 8-step wizard to gather app path, names, labels, and configuration options.

Returns:

  • dict[str, str]

    Dictionary containing all collected user inputs.

Source code in django_spire/core/management/commands/spire_startapp_pkg/user_input.py
def collect_all_inputs(self) -> dict[str, str]:
    """
    Collects all required user inputs for app creation.

    Guides the user through an 8-step wizard to gather app path, names,
    labels, and configuration options.

    :return: Dictionary containing all collected user inputs.
    """

    self.reporter.write('\n[App Creation Wizard]\n\n', self.reporter.style_success)

    app_path = self._collect_app_path()
    components = app_path.split('.')

    app_name = self._collect_app_name(components)
    app_label = self._collect_app_label(components, app_name)
    model_name = self._collect_model_name(app_name)
    model_name_plural = self._collect_model_name_plural(model_name)
    db_table_name = self._collect_db_table_name(components, app_name)  # Changed from app_label to components, app_name
    model_permission_path = self._collect_model_permission_path(app_path, model_name)

    permission_data = self._collect_permission_inheritance(components)

    verbose_name, verbose_name_plural = self._derive_verbose_names(model_name, model_name_plural)

    return {
        'app_path': app_path,
        'app_name': app_name,
        'model_name': model_name,
        'model_name_plural': model_name_plural,
        'app_label': app_label,
        'db_table_name': db_table_name,
        'model_permission_path': model_permission_path,
        'verbose_name': verbose_name,
        'verbose_name_plural': verbose_name_plural,
        **permission_data,
    }

AppValidator

Validates Django app paths and configurations.

This class performs validation checks to ensure app paths are properly formatted, don't conflict with existing apps, and use valid root apps.

Initializes the validator with required dependencies.

Parameters:

  • reporter (Reporter) –

    Reporter for displaying error messages.

  • registry (AppRegistry) –

    Registry for checking installed apps.

  • path_resolver (PathResolver) –

    Path resolver for determining file locations.

  • filesystem (FileSystem) –

    File system for checking file existence.

Source code in django_spire/core/management/commands/spire_startapp_pkg/validator.py
def __init__(
    self,
    reporter: Reporter,
    registry: AppRegistry,
    path_resolver: PathResolver,
    filesystem: FileSystem
):
    """
    Initializes the validator with required dependencies.

    :param reporter: Reporter for displaying error messages.
    :param registry: Registry for checking installed apps.
    :param path_resolver: Path resolver for determining file locations.
    :param filesystem: File system for checking file existence.
    """

    self._filesystem = filesystem
    self._path_resolver = path_resolver
    self._registry = registry
    self._reporter = reporter

validate_app_format

Validates that an app path uses dot notation.

Parameters:

  • app_path (str) –

    App path to validate.

Raises:

  • CommandError

    If the app path doesn't contain dots.

Source code in django_spire/core/management/commands/spire_startapp_pkg/validator.py
def validate_app_format(self, app_path: str) -> None:
    """
    Validates that an app path uses dot notation.

    :param app_path: App path to validate.
    :raises CommandError: If the app path doesn't contain dots.
    """

    if '.' not in app_path:
        self._reporter.write('\n', self._reporter.style_notice)

        message = 'Invalid app name format. The app path must use dot notation (e.g., "parent.child").'
        raise CommandError(message)

validate_app_path

Validates that an app path doesn't already exist.

Parameters:

  • components (list[str]) –

    List of app path components.

Raises:

  • CommandError

    If an app already exists at the destination path.

Source code in django_spire/core/management/commands/spire_startapp_pkg/validator.py
def validate_app_path(self, components: list[str]) -> None:
    """
    Validates that an app path doesn't already exist.

    :param components: List of app path components.
    :raises CommandError: If an app already exists at the destination path.
    """

    destination = self._path_resolver.get_app_destination(components)

    if self._filesystem.has_content(destination):
        self._reporter.write('\n', self._reporter.style_notice)

        message = (
            f'The app already exists at {destination}. '
            'Please remove the existing app or choose a different name.'
        )

        raise CommandError(message)

validate_root_app

Validates that the root app component is registered in Django.

Parameters:

  • components (list[str]) –

    List of app path components.

Raises:

  • CommandError

    If the root app is not a valid registered app.

Source code in django_spire/core/management/commands/spire_startapp_pkg/validator.py
def validate_root_app(self, components: list[str]) -> None:
    """
    Validates that the root app component is registered in Django.

    :param components: List of app path components.
    :raises CommandError: If the root app is not a valid registered app.
    """

    valid_roots = self._registry.get_valid_root_apps()
    root = components[0]

    if root not in valid_roots:
        self._reporter.write('\n', self._reporter.style_notice)

        message = (
            f'Invalid root app "{root}". '
            f'Valid root apps: {", ".join(sorted(valid_roots))}.'
        )

        raise CommandError(message)

generate_replacement_map

Generate replacement mappings for template processing.

Source code in django_spire/core/management/commands/spire_startapp_pkg/maps.py
def generate_replacement_map(
    components: list[str],
    user_inputs: dict[str, str] | None = None
) -> dict[str, str]:
    """Generate replacement mappings for template processing."""

    builder = ReplacementMapBuilder.build(components, user_inputs)
    replacement_dict = builder.to_dict()

    return {key: str(value) for key, value in replacement_dict.items()}