Code of Conduct
Feature Description
Add an executor_class attribute to the migrate management command, defaulting to MigrationExecutor, so subclasses can customize migration execution without overriding the full command implementation.
This would follow the existing migration command pattern used by attributes such as autodetector.
Problem
The migrate command currently instantiates MigrationExecutor directly inside its implementation.
This makes customization difficult for projects or third-party packages that need a custom migration executor.
Today, the practical workaround is to subclass the migrate command and copy large parts of handle() just to replace the executor construction line.
That approach is fragile because the copied logic can drift from Django upstream over time. It also makes small customizations unnecessarily expensive to maintain.
This feature would provide a small, explicit extension point while preserving the current default behavior.
Request or proposal
proposal
Additional Details
The proposed change is backwards compatible.
Existing behavior would remain unchanged because executor_class would default to MigrationExecutor.
The intended usage would be:
from django.core.management.commands.migrate import Command as MigrateCommand
from .executors import CustomMigrationExecutor
class Command(MigrateCommand):
executor_class = CustomMigrationExecutor
This is useful for projects that need to customize migration execution behavior while still relying on Django’s standard migrate command flow.
The change also aligns with the existing composition-style pattern used in Django’s migration commands, where collaborators can be exposed as class attributes rather than hard-coded directly inside command methods.
Implementation Suggestions
Add a class-level attribute to django.core.management.commands.migrate.Command:
class Command(BaseCommand):
executor_class = MigrationExecutor
Then replace direct MigrationExecutor construction with self.executor_class.
For example:
executor = self.executor_class(connection, self.migration_progress_callback)
For consistency, BaseCommand.check_migrations() could also resolve the executor class from the command instance when available:
executor_class = getattr(self, "executor_class", MigrationExecutor)
executor = executor_class(connections[DEFAULT_DB_ALIAS])
Tests should cover:
- migrate.Command.executor_class defaults to MigrationExecutor
- migrate.Command.handle() uses self.executor_class
- BaseCommand.check_migrations() respects a custom executor_class
- existing behavior remains unchanged when executor_class is not overridden
Documentation should mention that subclasses of the migrate command may override executor_class to customize migration execution behavior.
POC:
django/django#21358
Code of Conduct
Feature Description
Add an
executor_classattribute to the migrate management command, defaulting to MigrationExecutor, so subclasses can customize migration execution without overriding the full command implementation.This would follow the existing migration command pattern used by attributes such as autodetector.
Problem
The migrate command currently instantiates MigrationExecutor directly inside its implementation.
This makes customization difficult for projects or third-party packages that need a custom migration executor.
Today, the practical workaround is to subclass the migrate command and copy large parts of handle() just to replace the executor construction line.
That approach is fragile because the copied logic can drift from Django upstream over time. It also makes small customizations unnecessarily expensive to maintain.
This feature would provide a small, explicit extension point while preserving the current default behavior.
Request or proposal
proposal
Additional Details
The proposed change is backwards compatible.
Existing behavior would remain unchanged because
executor_classwould default to MigrationExecutor.The intended usage would be:
from django.core.management.commands.migrate import Command as MigrateCommand
from .executors import CustomMigrationExecutor
This is useful for projects that need to customize migration execution behavior while still relying on Django’s standard migrate command flow.
The change also aligns with the existing composition-style pattern used in Django’s migration commands, where collaborators can be exposed as class attributes rather than hard-coded directly inside command methods.
Implementation Suggestions
Add a class-level attribute to django.core.management.commands.migrate.Command:
Then replace direct MigrationExecutor construction with self.executor_class.
For example:
executor = self.executor_class(connection, self.migration_progress_callback)For consistency, BaseCommand.check_migrations() could also resolve the executor class from the command instance when available:
Tests should cover:
Documentation should mention that subclasses of the migrate command may override executor_class to customize migration execution behavior.
POC:
django/django#21358