def test_add_field_temp_default(self): """ Tests adding fields to models with a temporary default """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure there's no age field columns = self.column_classes(Author) self.assertNotIn("age", columns) # Add some rows of data Author.objects.create(name="Andrew", height=30) Author.objects.create(name="Andrea") # Add a not-null field new_field = CharField(max_length=30, default="Godwin") new_field.set_attributes_from_name("surname") with connection.schema_editor() as editor: editor.add_field( Author, new_field, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['surname'][0], "CharField") self.assertEqual(columns['surname'][1][6], connection.features.interprets_empty_strings_as_nulls)
def test_rename(self): """ Tests simple altering of fields """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure the field is right to begin with columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertNotIn("display_name", columns) # Alter the name field's name new_field = CharField(max_length=254) new_field.set_attributes_from_name("display_name") with connection.schema_editor() as editor: editor.alter_field( Author, Author._meta.get_field_by_name("name")[0], new_field, strict=True, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['display_name'][0], "CharField") self.assertNotIn("name", columns)
def test_add_field_temp_default(self): """ Tests adding fields to models with a temporary default """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure there's no age field columns = self.column_classes(Author) self.assertNotIn("age", columns) # Add some rows of data Author.objects.create(name="Andrew", height=30) Author.objects.create(name="Andrea") # Add a not-null field new_field = CharField(max_length=30, default="Godwin") new_field.set_attributes_from_name("surname") with connection.schema_editor() as editor: editor.add_field( Author, new_field, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['surname'][0], "CharField") self.assertEqual(columns['surname'][1][6], connection.features.interprets_empty_strings_as_nulls)
def test_rename(self): """ Tests simple altering of fields """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure the field is right to begin with columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertNotIn("display_name", columns) # Alter the name field's name new_field = CharField(max_length=254) new_field.set_attributes_from_name("display_name") with connection.schema_editor() as editor: editor.alter_field( Author, Author._meta.get_field_by_name("name")[0], new_field, strict=True, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['display_name'][0], "CharField") self.assertNotIn("name", columns)
def test_add_field_use_effective_default(self): """ #23987 - effective_default() should be used as the field default when adding a new field. """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure there's no surname field columns = self.column_classes(Author) self.assertNotIn("surname", columns) # Create a row Author.objects.create(name='Anonymous1') # Add new CharField to ensure default will be used from effective_default new_field = CharField(max_length=15, blank=True) new_field.set_attributes_from_name("surname") with connection.schema_editor() as editor: editor.add_field(Author, new_field) # Ensure field was added with the right default with connection.cursor() as cursor: cursor.execute("SELECT surname FROM schema_author;") item = cursor.fetchall()[0] self.assertEqual( item[0], None if connection.features.interprets_empty_strings_as_nulls else '')
def test_indexes(self): """ Tests creation/altering of indexes """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(Book) # Ensure the table is there and has the right index self.assertIn("title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table)) # Alter to remove the index new_field = CharField(max_length=100, db_index=False) new_field.set_attributes_from_name("title") with connection.schema_editor() as editor: editor.alter_field(Book, Book._meta.get_field_by_name("title")[0], new_field, strict=True) # Ensure the table is there and has no index self.assertNotIn("title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table)) # Alter to re-add the index with connection.schema_editor() as editor: editor.alter_field(Book, new_field, Book._meta.get_field_by_name("title")[0], strict=True) # Ensure the table is there and has the index again self.assertIn("title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table)) # Add a unique column, verify that creates an implicit index with connection.schema_editor() as editor: editor.add_field(Book, BookWithSlug._meta.get_field_by_name("slug")[0]) self.assertIn("slug", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table)) # Remove the unique, check the index goes with it new_field2 = CharField(max_length=20, unique=False) new_field2.set_attributes_from_name("slug") with connection.schema_editor() as editor: editor.alter_field(BookWithSlug, BookWithSlug._meta.get_field_by_name("slug")[0], new_field2, strict=True) self.assertNotIn("slug", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table))
def test_rename(self): """ Tests simple altering of fields """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure the field is right to begin with columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertNotIn("display_name", columns) # Alter the name field's name # The original test tried to resize the field from 255 to 254 # Firebird doesn''t allow change to a smaller size than you had before #new_field = CharField(max_length=254) new_field = CharField(max_length=256) new_field.set_attributes_from_name("display_name") with connection.schema_editor() as editor: editor.alter_field( Author, Author._meta.get_field_by_name("name")[0], new_field, strict=True, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['display_name'][0], "CharField") self.assertNotIn("name", columns)
def test_field_rename_inside_atomic_block(self): """ NotImplementedError is raised when a model field rename is attempted inside an atomic block. """ new_field = CharField(max_length=255, unique=True) new_field.set_attributes_from_name('renamed') msg = ("Renaming the 'backends_author'.'name' column while in a " "transaction is not supported on SQLite because it would break " "referential integrity. Try adding `atomic = False` to the " "Migration class.") with self.assertRaisesMessage(NotSupportedError, msg): with connection.schema_editor(atomic=True) as editor: editor.alter_field(Author, Author._meta.get_field('name'), new_field)
def test_field_rename_inside_atomic_block(self): """ NotImplementedError is raised when a model field rename is attempted inside an atomic block. """ new_field = CharField(max_length=255, unique=True) new_field.set_attributes_from_name('renamed') msg = ( "Renaming the 'backends_author'.'name' column while in a " "transaction is not supported on SQLite < 3.26 because it would " "break referential integrity. Try adding `atomic = False` to the " "Migration class." ) with self.assertRaisesMessage(NotSupportedError, msg): with connection.schema_editor(atomic=True) as editor: editor.alter_field(Author, Author._meta.get_field('name'), new_field)
def test_alter(self): """ Tests simple altering of fields Firebird: changes from varchar to Text (blob sub_type 1) is nor allowed """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure the field is right to begin with columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertEqual(bool(columns['name'][1][6]), bool(connection.features.interprets_empty_strings_as_nulls)) # Alter the name field to a CharField new_field = CharField(max_length=2000, null=True) new_field.set_attributes_from_name("name") with connection.schema_editor() as editor: editor.alter_field( Author, Author._meta.get_field_by_name("name")[0], new_field, strict=True, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertEqual(columns['name'][1][6], True) # Is null? # Change nullability again new_field2 = CharField(max_length=2000, null=False) new_field2.set_attributes_from_name("name") with connection.schema_editor() as editor: editor.alter_field( Author, new_field, new_field2, strict=True, ) # Ensure the field is right afterwards columns = self.column_classes(Author) self.assertEqual(columns['name'][0], "CharField") self.assertEqual(bool(columns['name'][1][6]), False)
def test_add_field_use_effective_default(self): """ #23987 - effective_default() should be used as the field default when adding a new field. """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) # Ensure there's no surname field columns = self.column_classes(Author) self.assertNotIn("surname", columns) # Create a row Author.objects.create(name='Anonymous1') # Add new CharField to ensure default will be used from effective_default new_field = CharField(max_length=15, blank=True) new_field.set_attributes_from_name("surname") with connection.schema_editor() as editor: editor.add_field(Author, new_field) # Ensure field was added with the right default with connection.cursor() as cursor: cursor.execute("SELECT surname FROM schema_author;") item = cursor.fetchall()[0] self.assertEqual(item[0], None if connection.features.interprets_empty_strings_as_nulls else '')
def test_indexes(self): """ Tests creation/altering of indexes """ # Create the table with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(Book) # Ensure the table is there and has the right index self.assertIn( "title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table), ) # Alter to remove the index new_field = CharField(max_length=100, db_index=False) new_field.set_attributes_from_name("title") with connection.schema_editor() as editor: editor.alter_field( Book, Book._meta.get_field_by_name("title")[0], new_field, strict=True, ) # Ensure the table is there and has no index self.assertNotIn( "title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table), ) # Alter to re-add the index with connection.schema_editor() as editor: editor.alter_field( Book, new_field, Book._meta.get_field_by_name("title")[0], strict=True, ) # Ensure the table is there and has the index again self.assertIn( "title", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table), ) # Add a unique column, verify that creates an implicit index with connection.schema_editor() as editor: editor.add_field( Book, BookWithSlug._meta.get_field_by_name("slug")[0], ) self.assertIn( "slug", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table), ) # Remove the unique, check the index goes with it new_field2 = CharField(max_length=20, unique=False) new_field2.set_attributes_from_name("slug") with connection.schema_editor() as editor: editor.alter_field( BookWithSlug, BookWithSlug._meta.get_field_by_name("slug")[0], new_field2, strict=True, ) self.assertNotIn( "slug", connection.introspection.get_indexes(connection.cursor(), Book._meta.db_table), )