After a few days with no answer, I went ahead and figured out a solution. This SO answer was a good starting point.
from django.db.migrations.executor import MigrationExecutor
from django.db import connections, DEFAULT_DB_ALIAS
def are_migrations_reversible(target_migrations, database=DEFAULT_DB_ALIAS):
"""check if all migrations required to reach the target migrations are reversible
`target_migrations` is an iterable of (app_label, migration_name) 2-tuples.
"""
connection = connections[database]
connection.prepare_database()
executor = MigrationExecutor(connection)
migration_plan = executor.migration_plan(list(target_migrations))
return all(
operation.reversible
for (migration, is_backwards) in migration_plan
for operation in migration.operations
)
The above requires figuring out the target migrations, which can easily be extracted from the output of the showmigrations
management command, or with some more effort with further use of the internal Django migrations code.