summaryrefslogtreecommitdiff
path: root/tests/migrations
diff options
context:
space:
mode:
authorMarkus Holtermann <info@markusholtermann.eu>2014-10-07 01:53:21 +0200
committerLoic Bistuer <loic.bistuer@gmail.com>2014-10-09 22:41:27 +0700
commit71988ed953131908fa2a1ba9fac294cedaa6e6c9 (patch)
tree6100d3bd52bf3fc3186536f4e64664b2c9c1b34a /tests/migrations
parente31be40f163e7d478946530acb1068c6deadb845 (diff)
[1.7.x] Fixed #23609 -- Fixed IntegrityError that prevented altering a NULL column into a NOT NULL one due to existing rows
Thanks to Simon Charette, Loic Bistuer and Tim Graham for the review. Backport of f633ba778d from master
Diffstat (limited to 'tests/migrations')
-rw-r--r--tests/migrations/test_autodetector.py75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py
index c58b41de30..56596309be 100644
--- a/tests/migrations/test_autodetector.py
+++ b/tests/migrations/test_autodetector.py
@@ -26,6 +26,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))])
+ author_name_null = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200, null=True))])
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_name_default = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200, default='Ada Lovelace'))])
@@ -275,6 +276,80 @@ class AutodetectorTests(TestCase):
action = migration.operations[0]
self.assertEqual(action.__class__.__name__, "AlterField")
self.assertEqual(action.name, "name")
+ self.assertTrue(action.preserve_default)
+
+ def test_alter_field_to_not_null_with_default(self):
+ "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ class CustomQuestioner(MigrationQuestioner):
+ def ask_not_null_alteration(self, field_name, model_name):
+ raise Exception("Should not have prompted for not null addition")
+
+ # Make state
+ before = self.make_project_state([self.author_name_null])
+ after = self.make_project_state([self.author_name_default])
+ autodetector = MigrationAutodetector(before, after, CustomQuestioner())
+ 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__, "AlterField")
+ self.assertEqual(action.name, "name")
+ self.assertTrue(action.preserve_default)
+ self.assertEqual(action.field.default, 'Ada Lovelace')
+
+ def test_alter_field_to_not_null_without_default(self):
+ "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ class CustomQuestioner(MigrationQuestioner):
+ def ask_not_null_alteration(self, field_name, model_name):
+ # Ignore for now, and let me handle existing rows with NULL
+ # myself (e.g. adding a RunPython or RunSQL operation in the new
+ # migration file before the AlterField operation)
+ return models.NOT_PROVIDED
+
+ # Make state
+ before = self.make_project_state([self.author_name_null])
+ after = self.make_project_state([self.author_name])
+ autodetector = MigrationAutodetector(before, after, CustomQuestioner())
+ 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__, "AlterField")
+ self.assertEqual(action.name, "name")
+ self.assertTrue(action.preserve_default)
+ self.assertIs(action.field.default, models.NOT_PROVIDED)
+
+ def test_alter_field_to_not_null_oneoff_default(self):
+ "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ class CustomQuestioner(MigrationQuestioner):
+ def ask_not_null_alteration(self, field_name, model_name):
+ # Provide a one-off default now (will be set on all existing rows)
+ return 'Some Name'
+
+ # Make state
+ before = self.make_project_state([self.author_name_null])
+ after = self.make_project_state([self.author_name])
+ autodetector = MigrationAutodetector(before, after, CustomQuestioner())
+ 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__, "AlterField")
+ self.assertEqual(action.name, "name")
+ self.assertFalse(action.preserve_default)
+ self.assertEqual(action.field.default, "Some Name")
def test_rename_field(self):
"Tests autodetection of renamed fields"