summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Guermond <sarah.guermond@gmail.com>2018-07-15 20:32:47 -0700
committerTim Graham <timograham@gmail.com>2018-11-14 18:22:59 -0500
commitcd40306854bdeec7d961e3715fba0ba9f72f2f88 (patch)
treefed3e00864ffb6859d2773520ce984cf238d808c
parente81955401885a93a459bcc130642b6ea5bf4ba4d (diff)
Fixed #25884 -- Fixed migrate --run-syncdb when specifying an app label.
-rw-r--r--django/core/management/commands/migrate.py25
-rw-r--r--tests/migrations/migrations_test_apps/unmigrated_app_simple/__init__.py0
-rw-r--r--tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py9
-rw-r--r--tests/migrations/test_commands.py23
4 files changed, 51 insertions, 6 deletions
diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py
index f28816fcee..6efae2fc90 100644
--- a/django/core/management/commands/migrate.py
+++ b/django/core/management/commands/migrate.py
@@ -104,6 +104,7 @@ class Command(BaseCommand):
)
# 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.
@@ -112,7 +113,10 @@ class Command(BaseCommand):
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']:
@@ -152,15 +156,21 @@ class Command(BaseCommand):
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: ") +
@@ -187,7 +197,10 @@ class Command(BaseCommand):
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:
diff --git a/tests/migrations/migrations_test_apps/unmigrated_app_simple/__init__.py b/tests/migrations/migrations_test_apps/unmigrated_app_simple/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unmigrated_app_simple/__init__.py
diff --git a/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py b/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py
new file mode 100644
index 0000000000..785d040800
--- /dev/null
+++ b/tests/migrations/migrations_test_apps/unmigrated_app_simple/models.py
@@ -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
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 2548804677..c2891ed1a1 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -663,6 +663,29 @@ class MigrateTests(MigrationTestBase):
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):
"""