Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Autodetect field renames. HAHAHA. AHAHAHAHA. YES.

  • Loading branch information...
commit 92a10f5552315b22e7d374123e3d09249b6b9883 1 parent 0e8ee50
Andrew Godwin authored June 20, 2013
21  django/db/migrations/autodetector.py
@@ -68,7 +68,26 @@ def changes(self):
68 68
             old_field_names = set([x for x, y in old_model_state.fields])
69 69
             new_field_names = set([x for x, y in new_model_state.fields])
70 70
             for field_name in new_field_names - old_field_names:
71  
-                field = [y for x, y in new_model_state.fields if x == field_name][0]
  71
+                field = new_model_state.get_field_by_name(field_name)
  72
+                # Scan to see if this is actually a rename!
  73
+                field_dec = field.deconstruct()[1:]
  74
+                found_rename = False
  75
+                for removed_field_name in (old_field_names - new_field_names):
  76
+                    if old_model_state.get_field_by_name(removed_field_name).deconstruct()[1:] == field_dec:
  77
+                        self.add_to_migration(
  78
+                            app_label,
  79
+                            operations.RenameField(
  80
+                                model_name = model_name,
  81
+                                old_name = removed_field_name,
  82
+                                new_name = field_name,
  83
+                            )
  84
+                        )
  85
+                        old_field_names.remove(removed_field_name)
  86
+                        new_field_names.remove(field_name)
  87
+                        found_rename = True
  88
+                        break
  89
+                if found_rename:
  90
+                    continue
72 91
                 # You can't just add NOT NULL fields with no default
73 92
                 if not field.null and not field.has_default():
74 93
                     field.default = self.questioner.ask_not_null_addition(field_name, model_name)
21  tests/migrations/test_autodetector.py
@@ -14,6 +14,7 @@ class AutodetectorTests(TestCase):
14 14
     author_empty = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True))])
15 15
     author_name = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200))])
16 16
     author_name_longer = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=400))])
  17
+    author_name_renamed = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("names", models.CharField(max_length=200))])
17 18
     other_pony = ModelState("otherapp", "Pony", [("id", models.AutoField(primary_key=True))])
18 19
     other_stable = ModelState("otherapp", "Stable", [("id", models.AutoField(primary_key=True))])
19 20
     third_thing = ModelState("thirdapp", "Thing", [("id", models.AutoField(primary_key=True))])
@@ -22,7 +23,7 @@ def make_project_state(self, model_states):
22 23
         "Shortcut to make ProjectStates from lists of predefined models"
23 24
         project_state = ProjectState()
24 25
         for model_state in model_states:
25  
-            project_state.add_model_state(model_state)
  26
+            project_state.add_model_state(model_state.clone())
26 27
         return project_state
27 28
 
28 29
     def test_arrange_for_graph(self):
@@ -148,3 +149,21 @@ def test_alter_field(self):
148 149
         action = migration.operations[0]
149 150
         self.assertEqual(action.__class__.__name__, "AlterField")
150 151
         self.assertEqual(action.name, "name")
  152
+
  153
+    def test_rename_field(self):
  154
+        "Tests autodetection of renamed fields"
  155
+        # Make state
  156
+        before = self.make_project_state([self.author_name])
  157
+        after = self.make_project_state([self.author_name_renamed])
  158
+        autodetector = MigrationAutodetector(before, after)
  159
+        changes = autodetector.changes()
  160
+        # Right number of migrations?
  161
+        self.assertEqual(len(changes['testapp']), 1)
  162
+        # Right number of actions?
  163
+        migration = changes['testapp'][0]
  164
+        self.assertEqual(len(migration.operations), 1)
  165
+        # Right action?
  166
+        action = migration.operations[0]
  167
+        self.assertEqual(action.__class__.__name__, "RenameField")
  168
+        self.assertEqual(action.old_name, "name")
  169
+        self.assertEqual(action.new_name, "names")

0 notes on commit 92a10f5

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