Skip to content

Commit

Permalink
Fixed #25884 -- Fixed migrate --run-syncdb when specifying an app label.
Browse files Browse the repository at this point in the history
  • Loading branch information
sguermond authored and timgraham committed Nov 14, 2018
1 parent e819554 commit cd40306
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 6 deletions.
25 changes: 19 additions & 6 deletions django/core/management/commands/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def handle(self, *args, **options):
)

# If they supplied command line arguments, work out what they mean.
run_syncdb = options['run_syncdb']
target_app_labels_only = True
if options['app_label']:
# Validate app_label.
Expand All @@ -112,7 +113,10 @@ def handle(self, *args, **options):
apps.get_app_config(app_label)
except LookupError as err:
raise CommandError(str(err))
if app_label not in executor.loader.migrated_apps:
if run_syncdb:
if app_label in executor.loader.migrated_apps:
raise CommandError("Can't use run_syncdb with app '%s' as it has migrations." % app_label)
elif app_label not in executor.loader.migrated_apps:
raise CommandError("App '%s' does not have migrations." % app_label)

if options['app_label'] and options['migration_name']:
Expand Down Expand Up @@ -152,15 +156,21 @@ def handle(self, *args, **options):
self.stdout.write(' ' + message, style)
return

# At this point, ignore run_syncdb if there aren't any apps to sync.
run_syncdb = options['run_syncdb'] and executor.loader.unmigrated_apps
# Print some useful info
if self.verbosity >= 1:
self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:"))
if run_syncdb:
self.stdout.write(
self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") +
(", ".join(sorted(executor.loader.unmigrated_apps)))
)
if options['app_label']:
self.stdout.write(
self.style.MIGRATE_LABEL(" Synchronize unmigrated app: %s" % app_label)
)
else:
self.stdout.write(
self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") +
(", ".join(sorted(executor.loader.unmigrated_apps)))
)
if target_app_labels_only:
self.stdout.write(
self.style.MIGRATE_LABEL(" Apply all migrations: ") +
Expand All @@ -187,7 +197,10 @@ def handle(self, *args, **options):
if run_syncdb:
if self.verbosity >= 1:
self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
self.sync_apps(connection, executor.loader.unmigrated_apps)
if options['app_label']:
self.sync_apps(connection, [app_label])
else:
self.sync_apps(connection, executor.loader.unmigrated_apps)

# Migrate!
if self.verbosity >= 1:
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.db import models


class UnmigratedModel(models.Model):
"""
A model that is in a migration-less app (which this app is
if its migrations directory has not been repointed)
"""
pass
23 changes: 23 additions & 0 deletions tests/migrations/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,29 @@ def test_migrate_syncdb_deferred_sql_executed_with_schemaeditor(self):
table_name = truncate_name('unmigrated_app_syncdb_classroom', connection.ops.max_name_length())
self.assertIn('Creating table %s' % table_name, stdout)

@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
def test_migrate_syncdb_app_with_migrations(self):
msg = "Can't use run_syncdb with app 'migrations' as it has migrations."
with self.assertRaisesMessage(CommandError, msg):
call_command('migrate', 'migrations', run_syncdb=True, verbosity=0)

@override_settings(INSTALLED_APPS=[
'migrations.migrations_test_apps.unmigrated_app_syncdb',
'migrations.migrations_test_apps.unmigrated_app_simple',
])
def test_migrate_syncdb_app_label(self):
"""
Running migrate --run-syncdb with an app_label only creates tables for
the specified app.
"""
stdout = io.StringIO()
with mock.patch.object(BaseDatabaseSchemaEditor, 'execute') as execute:
call_command('migrate', 'unmigrated_app_syncdb', run_syncdb=True, stdout=stdout)
create_table_count = len([call for call in execute.mock_calls if 'CREATE TABLE' in str(call)])
self.assertEqual(create_table_count, 2)
self.assertGreater(len(execute.mock_calls), 2)
self.assertIn('Synchronize unmigrated app: unmigrated_app_syncdb', stdout.getvalue())

@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"})
def test_migrate_record_replaced(self):
"""
Expand Down

0 comments on commit cd40306

Please sign in to comment.