﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36602	Enhance showmigrations command with structured data collection and display separation	Aashay Amballi	Aashay Amballi	"Enhance the showmigrations command with structured data collection and display separation

Add a get_migration_data() method to the showmigrations command that returns migration data in a structured format, and modify show_list() to accept this data as a parameter. This separation enables better extensibility and customization while preserving all existing functionality.

Problem

The current showmigrations command tightly couples data collection with display logic, making it difficult to extend or customize the output format. Third-party packages and custom commands cannot easily access migration data in a structured format or customize the display without duplicating Django's internal logic.

Why Not Just Create a Custom Command?

While it's possible to create a custom command for specific needs, many use cases align closely with showmigrations functionality. Creating separate commands leads to:

- Code Duplication: Replicating Django's migration loading and graph traversal logic
- Maintenance Burden: Keeping custom commands in sync with Django's internal changes
- Fragmentation: Multiple similar commands across the ecosystem
- Lost Benefits: Missing Django's built-in features (app filtering, verbosity, etc.)

This enhancement would benefit the entire Django ecosystem by making showmigrations more extensible while preserving its core functionality.

Request or proposal

proposal

Separate data collection from display logic by introducing a get_migration_data() method that returns structured migration data, and modify show_list() to accept this data as a parameter.

Benefits:

- Extensibility: Third-party packages can easily access migration data
- Testability: Data collection and display can be tested independently
- Maintainability: Cleaner separation of concerns
- Reusability: Migration data can be used by other methods
- Ecosystem Health: Reduces code duplication across Django packages
- Output Flexibility: Complete control over how the showmigration result is displayed''

Proposed API:


{{{
class Command(BaseCommand):
    def handle(self, *args, **options):
        self.verbosity = options[""verbosity""]
        
        if options[""format""] == ""plan"":
            # We can apply a similar approach to the plan, also.
            return self.show_plan(connection, options[""app_label""])
        else:
            migration_data = self.get_migration_data(connection, options[""app_label""])
            return self.show_list(migration_data)
    
    def get_migration_data(self, connection, app_names=None):
        """"""
        Return migration data in structured format.
        
        Returns:
            dict: {""app_name"": [{""name"": ""0001_initial"", ""applied"": True, ...}, ...]}
        """"""
        # Current show_list logic moved here, but returns data instead of printing
        pass
    
    def show_list(self, migration_data):
        """"""
        Display migration data using provided data.
        
        Args:
            migration_data (dict): Migration data from get_migration_data()
        """"""
        # Display logic using migration_data parameter
        pass
}}}

get_migration_data return data structure


{{{
{
    ""app_name"": [
        {""name"": ""0001_initial"", ""applied"": True, ...},
        {""name"": ""0002_add_field"", ""applied"": False, ...},
        # ...
    ],
    # ...
}

}}}

Implementation Suggestions
Implementation Notes:

get_migration_data() should contain the current show_list() logic but return data instead of printing
show_list() should be refactored to use the data parameter
Both methods should be easily overridable by subclasses

Example Usage:


{{{
# Custom command extending showmigrations
class CustomShowMigrationsCommand(ShowMigrationsCommand):
    def get_migration_data(self, connection, app_names=None):
        data = super().get_migration_data(connection, app_names)
        # Add custom data (e.g., file sizes, creation dates, etc.), maybe based on some custom flags
        for app_name, migrations in data.items():
            for migration in migrations:
                migration_file = self.find_migration_file(app_name, migration[""name""])
                if migration_file:
                    migration[""file_size""] = migration_file.stat().st_size
                    migration[""created_at""] = migration_file.stat().st_ctime
        return data
    
    def show_list(self, migration_data):
        # Custom display format with file sizes
        for app_name, migrations in migration_data.items():
            for migration in migrations:
                status = ""✓"" if migration[""applied""] else ""✗""
                file_size = migration.get(""file_size"", 0)
                self.stdout.write(f"" {status} {app_name}.{migration['name']} ({file_size} bytes)"")
}}}
"	New feature	assigned	Core (Management commands)	dev	Normal		showmigrations	Aashay Amballi	Accepted	1	0	0	0	0	0
