From 3f8979e37b6c498101d09a583ccc521d7f2879e5 Mon Sep 17 00:00:00 2001 From: Daniel Ebrahimian Date: Thu, 14 Jan 2021 11:08:27 +1100 Subject: [PATCH] Fixed #32350 -- Fixed showmigrations crash for applied squashed migrations. Thanks Simon Charette for reviews. --- .../management/commands/showmigrations.py | 2 +- tests/migrations/test_commands.py | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/django/core/management/commands/showmigrations.py b/django/core/management/commands/showmigrations.py index 48bea1f3f0..e62a1b8593 100644 --- a/django/core/management/commands/showmigrations.py +++ b/django/core/management/commands/showmigrations.py @@ -92,7 +92,7 @@ class Command(BaseCommand): # Mark it as applied/unapplied if applied_migration: output = ' [X] %s' % title - if self.verbosity >= 2: + if self.verbosity >= 2 and hasattr(applied_migration, 'applied'): output += ' (applied at %s)' % applied_migration.applied.strftime('%Y-%m-%d %H:%M:%S') self.stdout.write(output) else: diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 2477872423..9346ba63e9 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -335,6 +335,44 @@ class MigrateTests(MigrationTestBase): # Cleanup by unmigrating everything call_command("migrate", "migrations", "zero", verbosity=0) + @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'}) + def test_showmigrations_list_squashed(self): + out = io.StringIO() + call_command('showmigrations', format='list', stdout=out, verbosity=2, no_color=True) + self.assertEqual( + 'migrations\n' + ' [ ] 0001_squashed_0002 (2 squashed migrations)\n', + out.getvalue().lower(), + ) + out = io.StringIO() + call_command( + 'migrate', + 'migrations', + '0001_squashed_0002', + stdout=out, + verbosity=2, + no_color=True, + ) + try: + self.assertIn( + 'operations to perform:\n' + ' target specific migration: 0001_squashed_0002, from migrations\n' + 'running pre-migrate handlers for application migrations\n' + 'running migrations:\n' + ' applying migrations.0001_squashed_0002... ok (', + out.getvalue().lower(), + ) + out = io.StringIO() + call_command('showmigrations', format='list', stdout=out, verbosity=2, no_color=True) + self.assertEqual( + 'migrations\n' + ' [x] 0001_squashed_0002 (2 squashed migrations)\n', + out.getvalue().lower(), + ) + finally: + # Unmigrate everything. + call_command('migrate', 'migrations', 'zero', verbosity=0) + @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_run_before"}) def test_showmigrations_plan(self): """