Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add operation that renames tables

  • Loading branch information...
commit 6f667999e1186b8eaa9c86e4cbd80d5c0ba20576 1 parent 73e30e9
@andrewgodwin andrewgodwin authored
View
6 django/db/backends/schema.py
@@ -362,9 +362,9 @@ def alter_field(self, model, old_field, new_field, strict=False):
return self._alter_many_to_many(model, old_field, new_field, strict)
elif old_type is None or new_type is None:
raise ValueError("Cannot alter field %s into %s - they are not compatible types (probably means only one is an M2M with implicit through model)" % (
- old_field,
- new_field,
- ))
+ old_field,
+ new_field,
+ ))
# Has unique been removed?
if old_field.unique and not new_field.unique:
# Find the unique constraint for this field
View
2  django/db/migrations/operations/__init__.py
@@ -1,2 +1,2 @@
-from .models import CreateModel, DeleteModel
+from .models import CreateModel, DeleteModel, AlterModelTable
from .fields import AddField, RemoveField
View
28 django/db/migrations/operations/models.py
@@ -50,3 +50,31 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state):
def describe(self):
return "Delete model %s" % (self.name, )
+
+
+class AlterModelTable(Operation):
+ """
+ Renames a model's table
+ """
+
+ def __init__(self, name, table):
+ self.name = name
+ self.table = table
+
+ def state_forwards(self, app_label, state):
+ state.models[app_label, self.name.lower()].options["db_table"] = self.table
+
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
+ old_app_cache = from_state.render()
+ new_app_cache = to_state.render()
+ schema_editor.alter_db_table(
+ new_app_cache.get_model(app_label, self.name),
+ old_app_cache.get_model(app_label, self.name)._meta.db_table,
+ new_app_cache.get_model(app_label, self.name)._meta.db_table,
+ )
+
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
+ return self.database_forwards(app_label, schema_editor, from_state, to_state)
+
+ def describe(self):
+ return "Rename table for %s to %s" % (self.name, self.table)
View
35 tests/migrations/test_autodetector.py
@@ -12,6 +12,7 @@ class AutodetectorTests(TestCase):
"""
author_empty = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True))])
+ author_name = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200))])
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))])
@@ -95,3 +96,37 @@ def test_old_model(self):
action = migration.operations[0]
self.assertEqual(action.__class__.__name__, "DeleteModel")
self.assertEqual(action.name, "Author")
+
+ def test_add_field(self):
+ "Tests autodetection of new fields"
+ # Make state
+ before = self.make_project_state([self.author_empty])
+ after = self.make_project_state([self.author_name])
+ autodetector = MigrationAutodetector(before, after)
+ changes = autodetector.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__, "AddField")
+ self.assertEqual(action.name, "name")
+
+ def test_remove_field(self):
+ "Tests autodetection of removed fields"
+ # Make state
+ before = self.make_project_state([self.author_name])
+ after = self.make_project_state([self.author_empty])
+ autodetector = MigrationAutodetector(before, after)
+ changes = autodetector.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__, "RemoveField")
+ self.assertEqual(action.name, "name")
View
43 tests/migrations/test_operations.py
@@ -114,3 +114,46 @@ def test_add_field(self):
with connection.schema_editor() as editor:
operation.database_backwards("test_adfl", editor, new_state, project_state)
self.assertColumnNotExists("test_adfl_pony", "height")
+
+ def test_remove_field(self):
+ """
+ Tests the RemoveField operation.
+ """
+ project_state = self.set_up_test_model("test_rmfl")
+ # Test the state alteration
+ operation = migrations.RemoveField("Pony", "pink")
+ new_state = project_state.clone()
+ operation.state_forwards("test_rmfl", new_state)
+ self.assertEqual(len(new_state.models["test_rmfl", "pony"].fields), 1)
+ # Test the database alteration
+ self.assertColumnExists("test_rmfl_pony", "pink")
+ with connection.schema_editor() as editor:
+ operation.database_forwards("test_rmfl", editor, project_state, new_state)
+ self.assertColumnNotExists("test_rmfl_pony", "pink")
+ # And test reversal
+ with connection.schema_editor() as editor:
+ operation.database_backwards("test_rmfl", editor, new_state, project_state)
+ self.assertColumnExists("test_rmfl_pony", "pink")
+
+ def test_alter_model_table(self):
+ """
+ Tests the AlterModelTable operation.
+ """
+ project_state = self.set_up_test_model("test_almota")
+ # Test the state alteration
+ operation = migrations.AlterModelTable("Pony", "test_almota_pony_2")
+ new_state = project_state.clone()
+ operation.state_forwards("test_almota", new_state)
+ self.assertEqual(new_state.models["test_almota", "pony"].options["db_table"], "test_almota_pony_2")
+ # Test the database alteration
+ self.assertTableExists("test_almota_pony")
+ self.assertTableNotExists("test_almota_pony_2")
+ with connection.schema_editor() as editor:
+ operation.database_forwards("test_almota", editor, project_state, new_state)
+ self.assertTableNotExists("test_almota_pony")
+ self.assertTableExists("test_almota_pony_2")
+ # And test reversal
+ with connection.schema_editor() as editor:
+ operation.database_backwards("test_almota", editor, new_state, project_state)
+ self.assertTableExists("test_almota_pony")
+ self.assertTableNotExists("test_almota_pony_2")
Please sign in to comment.
Something went wrong with that request. Please try again.