Skip to content

spire_startapp

django_spire.core.management.commands.spire_startapp

Command

Bases: BaseCommand

Django management command for creating custom Spire apps.

This command guides users through an interactive wizard to create a new Django app with a pre-configured structure including models, views, forms, services, and templates. It handles nested app structures (e.g., app.parent.child) and validates that all parent apps are properly registered before creating child apps.

help = 'Create a custom Spire app.' class-attribute instance-attribute

handle

Main entry point for the management command.

Orchestrates the entire app creation process by initializing helper classes, collecting user input through an interactive wizard, validating the app structure, generating app files and templates, and providing feedback to the user.

Parameters:

  • args (Any, default: () ) –

    Positional arguments (not used).

  • kwargs (Any, default: {} ) –

    Keyword arguments (not used).

Source code in django_spire/core/management/commands/spire_startapp.py
def handle(self, *args: Any, **kwargs: Any) -> None:
    """
    Main entry point for the management command.

    Orchestrates the entire app creation process by initializing helper classes,
    collecting user input through an interactive wizard, validating the app structure,
    generating app files and templates, and providing feedback to the user.

    :param args: Positional arguments (not used).
    :param kwargs: Keyword arguments (not used).
    """

    filesystem = FileSystem()
    path_config = PathConfig.default()
    path_resolver = PathResolver()
    registry = AppRegistry()
    reporter = Reporter(self)

    template_engine = TemplateEngine()
    template_processor = TemplateProcessor(template_engine, filesystem)

    validator = AppValidator(reporter, registry, path_resolver, filesystem)

    user_input_collector = UserInputCollector(reporter, validator)

    config_factory = AppConfigFactory(path_resolver)

    template_builder = TemplateBuilder(reporter)

    app_generator = AppGenerator(filesystem, template_processor, reporter, path_config)
    template_generator = TemplateGenerator(filesystem, template_processor, reporter, path_config)

    user_inputs = user_input_collector.collect_all_inputs()
    app_path = user_inputs['app_path']

    skip_app_generation = user_inputs['skip_app_generation']
    skip_template_generation = user_inputs['skip_template_generation']

    if skip_app_generation and skip_template_generation:
        reporter.write('Skipped file generation.', reporter.style_notice)
        return

    validator.validate_app_format(app_path)

    config = config_factory.create_config(app_path, user_inputs)
    validator.validate_root_app(config.components)

    reporter.write(
        f'\nChecking app components: {config.components}\n',
        reporter.style_notice
    )

    if not skip_app_generation:
        missing = registry.get_missing_components(config.components)

        if missing:
            reporter.report_missing_components(missing)

            template_builder.build_app_tree_structure(
                path_resolver.get_base_dir(),
                config.components,
                registry.get_installed_apps(),
                path_config.app_template
            )

            if reporter.prompt_confirmation('\nProceed with app creation? (y/n): '):
                for module in [missing[-1]]:
                    module_config = config_factory.create_config(module, user_inputs)

                app_generator.generate(module_config)

                reporter.report_installed_apps_suggestion(missing)
            else:
                reporter.write('Skipping app creation.', reporter.style_notice)

        else:
            reporter.write('All component(s) exist.', reporter.style_success)

    if not skip_template_generation:
        template_builder.build_html_tree_structure(
            path_resolver.get_base_dir(),
            config.components,
            registry.get_installed_apps(),
            path_config.html_template
        )

        if not reporter.prompt_confirmation('\nProceed with template creation? (y/n): '):
            reporter.write('Skipping template creation.', reporter.style_notice)
            return

        template_generator.generate(config)