diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index db5c5e34e9..ec65d29321 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -94,9 +94,14 @@ class MigrationAutodetector(object): # Phase 2 is progressively adding pending models, splitting up into two # migrations if required. pending_new_fks = [] + added_phase_2 = set() while pending_add: # Is there one we can add that has all dependencies satisfied? - satisfied = [(m, rf) for m, rf in pending_add.items() if all((al, mn) not in pending_add for f, al, mn in rf)] + satisfied = [ + (m, rf) + for m, rf in pending_add.items() + if all((al, mn) not in pending_add for f, al, mn in rf) + ] if satisfied: (app_label, model_name), related_fields = sorted(satisfied)[0] model_state = self.to_state.models[app_label, model_name] @@ -107,7 +112,10 @@ class MigrationAutodetector(object): fields=model_state.fields, options=model_state.options, bases=model_state.bases, - ) + ), + # If it's already been added in phase 2 put it in a new + # migration for safety. + new=any((al, mn) in added_phase_2 for f, al, mn in related_fields), ) for field_name, other_app_label, other_model_name in related_fields: # If it depends on a swappable something, add a dynamic depend'cy @@ -117,6 +125,7 @@ class MigrationAutodetector(object): elif app_label != other_app_label: self.add_dependency(app_label, other_app_label) del pending_add[app_label, model_name] + added_phase_2.add((app_label, model_name)) # Ah well, we'll need to split one. Pick deterministically. else: (app_label, model_name), related_fields = sorted(pending_add.items())[0] @@ -342,6 +351,7 @@ class MigrationAutodetector(object): else: new_name = "%04i_%s" % (next_number, self.suggest_name(migration.operations)) name_map[(app_label, migration.name)] = (app_label, new_name) + next_number += 1 migration.name = new_name # Now fix dependencies for app_label, migrations in changes.items(): diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 339630d9e8..c6133e6227 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -24,6 +24,7 @@ class AutodetectorTests(TestCase): author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author", )) publisher = ModelState("testapp", "Publisher", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=100))]) publisher_with_author = ModelState("testapp", "Publisher", [("id", models.AutoField(primary_key=True)), ("author", models.ForeignKey("testapp.Author")), ("name", models.CharField(max_length=100))]) + publisher_with_book = ModelState("testapp", "Publisher", [("id", models.AutoField(primary_key=True)), ("author", models.ForeignKey("otherapp.Book")), ("name", models.CharField(max_length=100))]) other_pony = ModelState("otherapp", "Pony", [("id", models.AutoField(primary_key=True))]) other_stable = ModelState("otherapp", "Stable", [("id", models.AutoField(primary_key=True))]) third_thing = ModelState("thirdapp", "Thing", [("id", models.AutoField(primary_key=True))]) @@ -243,7 +244,7 @@ class AutodetectorTests(TestCase): """ # Make state before = self.make_project_state([]) - after = self.make_project_state([self.author_with_book, self.book]) + after = self.make_project_state([self.author_with_book, self.book, self.publisher_with_book]) autodetector = MigrationAutodetector(before, after) changes = autodetector._detect_changes() # Right number of migrations? @@ -251,7 +252,7 @@ class AutodetectorTests(TestCase): self.assertEqual(len(changes['otherapp']), 2) # Right number of actions? migration1 = changes['testapp'][0] - self.assertEqual(len(migration1.operations), 1) + self.assertEqual(len(migration1.operations), 2) migration2 = changes['otherapp'][0] self.assertEqual(len(migration2.operations), 1) migration3 = changes['otherapp'][1]