From 8e73d3a2c17bd3233d5c6c560dda73f74083f44f Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Wed, 26 Mar 2014 03:51:15 +0800 Subject: [PATCH] [1.7.x] Fixed #22319 -- Fixed migration external dependencies when there are internal dependencies. Backport of 0fd51cf0bd from master --- django/db/migrations/autodetector.py | 23 ++++++++++++----------- tests/migrations/test_autodetector.py | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index e0631f8c82..adf3686d59 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -134,6 +134,7 @@ class MigrationAutodetector(object): bases=model_state.bases, ) ) + # Phase 2 is progressively adding pending models, splitting up into two # migrations if required. pending_new_fks = [] @@ -161,14 +162,6 @@ class MigrationAutodetector(object): # 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 - swappable_setting = new_apps.get_model(app_label, model_name)._meta.get_field_by_name(field_name)[0].swappable_setting - if swappable_setting is not None: - self.add_swappable_dependency(app_label, swappable_setting) - 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: @@ -194,8 +187,16 @@ class MigrationAutodetector(object): # Add the bad fields to be made in a phase 3 for field_name, (other_app_label, other_model_name) in bad_fields.items(): pending_new_fks.append((app_label, model_name, field_name, other_app_label)) - del pending_add[app_label, model_name] - # Phase 3 is adding the final set of FKs as separate new migrations + for field_name, other_app_label, other_model_name in related_fields: + # If it depends on a swappable something, add a dynamic depend'cy + swappable_setting = new_apps.get_model(app_label, model_name)._meta.get_field_by_name(field_name)[0].swappable_setting + if swappable_setting is not None: + self.add_swappable_dependency(app_label, swappable_setting) + elif app_label != other_app_label: + self.add_dependency(app_label, other_app_label) + del pending_add[app_label, model_name] + + # Phase 3 is adding the final set of FKs as separate new migrations. for app_label, model_name, field_name, other_app_label in pending_new_fks: model_state = self.to_state.models[app_label, model_name] self.add_to_migration( @@ -370,7 +371,7 @@ class MigrationAutodetector(object): Adds a dependency to app_label's newest migration on other_app_label's latest migration. """ - if self.migrations.get(other_app_label, []): + if self.migrations.get(other_app_label): dependency = (other_app_label, self.migrations[other_app_label][-1].name) else: dependency = (other_app_label, "__first__") diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 5ceadc7430..a56e31568a 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -343,7 +343,7 @@ class AutodetectorTests(TestCase): self.assertEqual(action.name, "author") # Right dependencies? self.assertEqual(migration1.dependencies, [("otherapp", "auto_1")]) - self.assertEqual(migration2.dependencies, []) + self.assertEqual(migration2.dependencies, [('testapp', '__first__')]) self.assertEqual(set(migration3.dependencies), set([("otherapp", "auto_1"), ("testapp", "auto_1")])) def test_same_app_circular_fk_dependency(self):