summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-07-29 09:38:08 -0700
committerAndrew Godwin <andrew@aeracode.org>2014-07-29 09:39:01 -0700
commit0a4fbf4e13b194383f9eecc0af337a50fb6dfe98 (patch)
treea76bcbc998050935b936a1fc9b0452751f30ff97
parentfb8ddac27afa2720226051cb0daff47bd0377a49 (diff)
[1.7.x] Fixed #23101: Prefer doing deletes before creates in autodetector.
Makes declined or missed renames still work (but drop data).
-rw-r--r--django/db/migrations/autodetector.py26
-rw-r--r--tests/migrations/test_autodetector.py35
2 files changed, 26 insertions, 35 deletions
diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py
index e27d8ace74..dd9595bd7e 100644
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -160,15 +160,16 @@ class MigrationAutodetector(object):
self.through_users[through_key] = (app_label, old_model_name, field_name)
# Generate non-rename model operations
- self.generate_created_models()
self.generate_deleted_models()
- self.generate_created_proxies()
+ self.generate_created_models()
self.generate_deleted_proxies()
+ self.generate_created_proxies()
self.generate_altered_options()
# Generate field operations
- self.generate_added_fields()
+ self.generate_renamed_fields()
self.generate_removed_fields()
+ self.generate_added_fields()
self.generate_altered_fields()
self.generate_altered_unique_together()
self.generate_altered_index_together()
@@ -682,17 +683,17 @@ class MigrationAutodetector(object):
),
)
- def generate_added_fields(self):
- # New fields
+ def generate_renamed_fields(self):
+ """
+ Works out renamed fields
+ """
self.renamed_fields = {}
for app_label, model_name, field_name in sorted(self.new_field_keys - self.old_field_keys):
old_model_name = self.renamed_models.get((app_label, model_name), model_name)
old_model_state = self.from_state.models[app_label, old_model_name]
- new_model_state = self.to_state.models[app_label, model_name]
field = self.new_apps.get_model(app_label, model_name)._meta.get_field_by_name(field_name)[0]
# Scan to see if this is actually a rename!
field_dec = self.deep_deconstruct(field)
- found_rename = False
for rem_app_label, rem_model_name, rem_field_name in sorted(self.old_field_keys - self.new_field_keys):
if rem_app_label == app_label and rem_model_name == model_name:
old_field_dec = self.deep_deconstruct(old_model_state.get_field_by_name(rem_field_name))
@@ -713,10 +714,15 @@ class MigrationAutodetector(object):
self.old_field_keys.remove((rem_app_label, rem_model_name, rem_field_name))
self.old_field_keys.add((app_label, model_name, field_name))
self.renamed_fields[app_label, model_name, field_name] = rem_field_name
- found_rename = True
break
- if found_rename:
- continue
+
+
+ def generate_added_fields(self):
+ """
+ Fields that have been added
+ """
+ for app_label, model_name, field_name in sorted(self.new_field_keys - self.old_field_keys):
+ field = self.new_apps.get_model(app_label, model_name)._meta.get_field_by_name(field_name)[0]
# Fields that are foreignkeys/m2ms depend on stuff
dependencies = []
if field.rel and field.rel.to:
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py
index 3e0195d0d2..096102ed78 100644
--- a/tests/migrations/test_autodetector.py
+++ b/tests/migrations/test_autodetector.py
@@ -276,16 +276,10 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name_renamed])
autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename": True}))
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__, "RenameField")
- self.assertEqual(action.old_name, "name")
- self.assertEqual(action.new_name, "names")
+ # Check
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["RenameField"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="name", new_name="names")
def test_rename_model(self):
"Tests autodetection of renamed models"
@@ -719,21 +713,12 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_with_publisher, self.publisher])
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), 3)
- # Right actions?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "CreateModel")
- self.assertEqual(action.name, "Publisher")
- action = migration.operations[1]
- self.assertEqual(action.__class__.__name__, "AddField")
- self.assertEqual(action.name, "publisher")
- action = migration.operations[2]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "publisher_name")
+ # Right result?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "RemoveField", "AddField"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Publisher")
+ self.assertOperationAttributes(changes, 'testapp', 0, 1, name="publisher_name")
+ self.assertOperationAttributes(changes, 'testapp', 0, 2, name="publisher")
def test_foreign_key_removed_before_target_model(self):
"""