Loading django/db/migrations/autodetector.py +15 −3 Original line number Diff line number Diff line Loading @@ -50,8 +50,20 @@ class MigrationAutodetector(object): self.migrations = {} old_app_cache = self.from_state.render() new_app_cache = self.to_state.render() # Prepare lists of old/new model keys that we care about # (i.e. ignoring proxy ones) old_model_keys = [ (al, mn) for al, mn in self.from_state.models.keys() if not old_app_cache.get_model(al, mn)._meta.proxy ] new_model_keys = [ (al, mn) for al, mn in self.to_state.models.keys() if not new_app_cache.get_model(al, mn)._meta.proxy ] # Adding models. Phase 1 is adding models with no outward relationships. added_models = set(self.to_state.models.keys()) - set(self.from_state.models.keys()) added_models = set(new_model_keys) - set(old_model_keys) pending_add = {} for app_label, model_name in added_models: model_state = self.to_state.models[app_label, model_name] Loading Loading @@ -130,7 +142,7 @@ class MigrationAutodetector(object): ) self.add_dependency(app_label, other_app_label) # Removing models removed_models = set(self.from_state.models.keys()) - set(self.to_state.models.keys()) removed_models = set(old_model_keys) - set(new_model_keys) for app_label, model_name in removed_models: model_state = self.from_state.models[app_label, model_name] self.add_to_migration( Loading @@ -140,7 +152,7 @@ class MigrationAutodetector(object): ) ) # Changes within models kept_models = set(self.from_state.models.keys()).intersection(self.to_state.models.keys()) kept_models = set(old_model_keys).intersection(new_model_keys) for app_label, model_name in kept_models: old_model_state = self.from_state.models[app_label, model_name] new_model_state = self.to_state.models[app_label, model_name] Loading tests/migrations/test_autodetector.py +27 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ class AutodetectorTests(TestCase): author_name_longer = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=400))]) author_name_renamed = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("names", models.CharField(max_length=200))]) author_with_book = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200)), ("book", models.ForeignKey("otherapp.Book"))]) author_proxy = ModelState("testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author", )) author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author", )) 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))]) Loading Loading @@ -272,3 +274,28 @@ class AutodetectorTests(TestCase): self.assertEqual(action.__class__.__name__, "AlterUniqueTogether") self.assertEqual(action.name, "book") self.assertEqual(action.unique_together, set([("title", "author")])) def test_proxy_ignorance(self): "Tests that the autodetector correctly ignores proxy models" # First, we test adding a proxy model before = self.make_project_state([self.author_empty]) after = self.make_project_state([self.author_empty, self.author_proxy]) autodetector = MigrationAutodetector(before, after) changes = autodetector._detect_changes() # Right number of migrations? self.assertEqual(len(changes), 0) # Now, we test turning a proxy model into a non-proxy model before = self.make_project_state([self.author_empty, self.author_proxy]) after = self.make_project_state([self.author_empty, self.author_proxy_notproxy]) autodetector = MigrationAutodetector(before, after) changes = autodetector._detect_changes() # Right number of migrations? self.assertEqual(len(changes['testapp']), 1) # Right number of actions? migration = changes['testapp'][0] self.assertEqual(len(migration.operations), 1) # Right action? action = migration.operations[0] self.assertEqual(action.__class__.__name__, "CreateModel") self.assertEqual(action.name, "AuthorProxy") Loading
django/db/migrations/autodetector.py +15 −3 Original line number Diff line number Diff line Loading @@ -50,8 +50,20 @@ class MigrationAutodetector(object): self.migrations = {} old_app_cache = self.from_state.render() new_app_cache = self.to_state.render() # Prepare lists of old/new model keys that we care about # (i.e. ignoring proxy ones) old_model_keys = [ (al, mn) for al, mn in self.from_state.models.keys() if not old_app_cache.get_model(al, mn)._meta.proxy ] new_model_keys = [ (al, mn) for al, mn in self.to_state.models.keys() if not new_app_cache.get_model(al, mn)._meta.proxy ] # Adding models. Phase 1 is adding models with no outward relationships. added_models = set(self.to_state.models.keys()) - set(self.from_state.models.keys()) added_models = set(new_model_keys) - set(old_model_keys) pending_add = {} for app_label, model_name in added_models: model_state = self.to_state.models[app_label, model_name] Loading Loading @@ -130,7 +142,7 @@ class MigrationAutodetector(object): ) self.add_dependency(app_label, other_app_label) # Removing models removed_models = set(self.from_state.models.keys()) - set(self.to_state.models.keys()) removed_models = set(old_model_keys) - set(new_model_keys) for app_label, model_name in removed_models: model_state = self.from_state.models[app_label, model_name] self.add_to_migration( Loading @@ -140,7 +152,7 @@ class MigrationAutodetector(object): ) ) # Changes within models kept_models = set(self.from_state.models.keys()).intersection(self.to_state.models.keys()) kept_models = set(old_model_keys).intersection(new_model_keys) for app_label, model_name in kept_models: old_model_state = self.from_state.models[app_label, model_name] new_model_state = self.to_state.models[app_label, model_name] Loading
tests/migrations/test_autodetector.py +27 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ class AutodetectorTests(TestCase): author_name_longer = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=400))]) author_name_renamed = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("names", models.CharField(max_length=200))]) author_with_book = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200)), ("book", models.ForeignKey("otherapp.Book"))]) author_proxy = ModelState("testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author", )) author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author", )) 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))]) Loading Loading @@ -272,3 +274,28 @@ class AutodetectorTests(TestCase): self.assertEqual(action.__class__.__name__, "AlterUniqueTogether") self.assertEqual(action.name, "book") self.assertEqual(action.unique_together, set([("title", "author")])) def test_proxy_ignorance(self): "Tests that the autodetector correctly ignores proxy models" # First, we test adding a proxy model before = self.make_project_state([self.author_empty]) after = self.make_project_state([self.author_empty, self.author_proxy]) autodetector = MigrationAutodetector(before, after) changes = autodetector._detect_changes() # Right number of migrations? self.assertEqual(len(changes), 0) # Now, we test turning a proxy model into a non-proxy model before = self.make_project_state([self.author_empty, self.author_proxy]) after = self.make_project_state([self.author_empty, self.author_proxy_notproxy]) autodetector = MigrationAutodetector(before, after) changes = autodetector._detect_changes() # Right number of migrations? self.assertEqual(len(changes['testapp']), 1) # Right number of actions? migration = changes['testapp'][0] self.assertEqual(len(migration.operations), 1) # Right action? action = migration.operations[0] self.assertEqual(action.__class__.__name__, "CreateModel") self.assertEqual(action.name, "AuthorProxy")