Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Migration autodetector now corerctly deals with proxy models

  • Loading branch information...
commit 05e14e8eaf577e64dc45e26466ebb6117589e572 1 parent a962286
Andrew Godwin authored September 06, 2013
18  django/db/migrations/autodetector.py
@@ -50,8 +50,20 @@ def _detect_changes(self):
50 50
         self.migrations = {}
51 51
         old_app_cache = self.from_state.render()
52 52
         new_app_cache = self.to_state.render()
  53
+        # Prepare lists of old/new model keys that we care about
  54
+        # (i.e. ignoring proxy ones)
  55
+        old_model_keys = [
  56
+            (al, mn)
  57
+            for al, mn in self.from_state.models.keys()
  58
+            if not old_app_cache.get_model(al, mn)._meta.proxy
  59
+        ]
  60
+        new_model_keys = [
  61
+            (al, mn)
  62
+            for al, mn in self.to_state.models.keys()
  63
+            if not new_app_cache.get_model(al, mn)._meta.proxy
  64
+        ]
53 65
         # Adding models. Phase 1 is adding models with no outward relationships.
54  
-        added_models = set(self.to_state.models.keys()) - set(self.from_state.models.keys())
  66
+        added_models = set(new_model_keys) - set(old_model_keys)
55 67
         pending_add = {}
56 68
         for app_label, model_name in added_models:
57 69
             model_state = self.to_state.models[app_label, model_name]
@@ -130,7 +142,7 @@ def _detect_changes(self):
130 142
             )
131 143
             self.add_dependency(app_label, other_app_label)
132 144
         # Removing models
133  
-        removed_models = set(self.from_state.models.keys()) - set(self.to_state.models.keys())
  145
+        removed_models = set(old_model_keys) - set(new_model_keys)
134 146
         for app_label, model_name in removed_models:
135 147
             model_state = self.from_state.models[app_label, model_name]
136 148
             self.add_to_migration(
@@ -140,7 +152,7 @@ def _detect_changes(self):
140 152
                 )
141 153
             )
142 154
         # Changes within models
143  
-        kept_models = set(self.from_state.models.keys()).intersection(self.to_state.models.keys())
  155
+        kept_models = set(old_model_keys).intersection(new_model_keys)
144 156
         for app_label, model_name in kept_models:
145 157
             old_model_state = self.from_state.models[app_label, model_name]
146 158
             new_model_state = self.to_state.models[app_label, model_name]
27  tests/migrations/test_autodetector.py
@@ -16,6 +16,8 @@ class AutodetectorTests(TestCase):
16 16
     author_name_longer = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=400))])
17 17
     author_name_renamed = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("names", models.CharField(max_length=200))])
18 18
     author_with_book = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200)), ("book", models.ForeignKey("otherapp.Book"))])
  19
+    author_proxy = ModelState("testapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author", ))
  20
+    author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author", ))
19 21
     other_pony = ModelState("otherapp", "Pony", [("id", models.AutoField(primary_key=True))])
20 22
     other_stable = ModelState("otherapp", "Stable", [("id", models.AutoField(primary_key=True))])
21 23
     third_thing = ModelState("thirdapp", "Thing", [("id", models.AutoField(primary_key=True))])
@@ -272,3 +274,28 @@ def test_unique_together_ordering(self):
272 274
         self.assertEqual(action.__class__.__name__, "AlterUniqueTogether")
273 275
         self.assertEqual(action.name, "book")
274 276
         self.assertEqual(action.unique_together, set([("title", "author")]))
  277
+
  278
+    def test_proxy_ignorance(self):
  279
+        "Tests that the autodetector correctly ignores proxy models"
  280
+        # First, we test adding a proxy model
  281
+        before = self.make_project_state([self.author_empty])
  282
+        after = self.make_project_state([self.author_empty, self.author_proxy])
  283
+        autodetector = MigrationAutodetector(before, after)
  284
+        changes = autodetector._detect_changes()
  285
+        # Right number of migrations?
  286
+        self.assertEqual(len(changes), 0)
  287
+
  288
+        # Now, we test turning a proxy model into a non-proxy model
  289
+        before = self.make_project_state([self.author_empty, self.author_proxy])
  290
+        after = self.make_project_state([self.author_empty, self.author_proxy_notproxy])
  291
+        autodetector = MigrationAutodetector(before, after)
  292
+        changes = autodetector._detect_changes()
  293
+        # Right number of migrations?
  294
+        self.assertEqual(len(changes['testapp']), 1)
  295
+        # Right number of actions?
  296
+        migration = changes['testapp'][0]
  297
+        self.assertEqual(len(migration.operations), 1)
  298
+        # Right action?
  299
+        action = migration.operations[0]
  300
+        self.assertEqual(action.__class__.__name__, "CreateModel")
  301
+        self.assertEqual(action.name, "AuthorProxy")

0 notes on commit 05e14e8

Please sign in to comment.
Something went wrong with that request. Please try again.