Loading django/db/backends/schema.py +3 −3 Original line number Diff line number Diff line Loading @@ -675,9 +675,9 @@ class BaseDatabaseSchemaEditor(object): } ) # Does it have a foreign key? if new_field.rel and \ (fks_dropped or (old_field.rel and not old_field.db_constraint)) and \ new_field.db_constraint: if (new_field.rel and (fks_dropped or not old_field.rel or not old_field.db_constraint) and new_field.db_constraint): self.execute(self._create_fk_sql(model, new_field, "_fk_%(to_table)s_%(to_column)s")) # Rebuild FKs that pointed to us if we previously had to drop them if old_field.primary_key and new_field.primary_key and old_type != new_type: Loading docs/releases/1.7.6.txt +3 −0 Original line number Diff line number Diff line Loading @@ -11,3 +11,6 @@ Bugfixes * Fixed crash when coercing ``ManyRelatedManager`` to a string (:ticket:`24352`). * Fixed a bug that prevented migrations from adding a FK constraint for an existing column. (:ticket:`24447`). tests/schema/models.py +9 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,15 @@ class BookWithM2M(models.Model): apps = new_apps class BookWithoutFK(models.Model): author = models.IntegerField() title = models.CharField(max_length=100, db_index=True) pub_date = models.DateTimeField() class Meta: apps = new_apps class TagThrough(models.Model): book = models.ForeignKey("schema.BookWithM2MThrough") tag = models.ForeignKey("schema.TagM2MTest") Loading tests/schema/tests.py +34 −2 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ from .fields import CustomManyToManyField, InheritedManyToManyField from .models import (Author, AuthorWithDefaultHeight, AuthorWithM2M, Book, BookWithLongName, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough, AuthorWithEvenLongerName, BookWeak, Note, BookWithO2O) AuthorWithEvenLongerName, BookWeak, Note, BookWithO2O, BookWithoutFK) class SchemaTests(TransactionTestCase): Loading @@ -29,7 +29,7 @@ class SchemaTests(TransactionTestCase): Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorWithEvenLongerName, BookWeak, BookWithO2O, BookWeak, BookWithO2O, BookWithoutFK, ] # Utility functions Loading Loading @@ -536,6 +536,38 @@ class SchemaTests(TransactionTestCase): else: self.fail("No FK constraint for author_id found") @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support") def test_alter_to_fk(self): """ #24447 - Tests adding a FK constraint for an existing column """ # Create the tables with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithoutFK) # Ensure no FK constraint exists constraints = self.get_constraints(BookWithoutFK._meta.db_table) for name, details in constraints.items(): if details['foreign_key']: self.fail('Found an unexpected FK constraint to %s' % details['columns']) new_field = ForeignKey(Author) new_field.set_attributes_from_name("author") with connection.schema_editor() as editor: editor.alter_field( BookWithoutFK, BookWithoutFK._meta.get_field_by_name("author")[0], new_field, strict=True, ) constraints = self.get_constraints(BookWithoutFK._meta.db_table) # Ensure FK constraint exists for name, details in constraints.items(): if details['foreign_key'] and details['columns'] == ["author_id"]: self.assertEqual(details['foreign_key'], ('schema_author', 'id')) break else: self.fail("No FK constraint for author_id found") @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support") def test_alter_o2o_to_fk(self): """ Loading Loading
django/db/backends/schema.py +3 −3 Original line number Diff line number Diff line Loading @@ -675,9 +675,9 @@ class BaseDatabaseSchemaEditor(object): } ) # Does it have a foreign key? if new_field.rel and \ (fks_dropped or (old_field.rel and not old_field.db_constraint)) and \ new_field.db_constraint: if (new_field.rel and (fks_dropped or not old_field.rel or not old_field.db_constraint) and new_field.db_constraint): self.execute(self._create_fk_sql(model, new_field, "_fk_%(to_table)s_%(to_column)s")) # Rebuild FKs that pointed to us if we previously had to drop them if old_field.primary_key and new_field.primary_key and old_type != new_type: Loading
docs/releases/1.7.6.txt +3 −0 Original line number Diff line number Diff line Loading @@ -11,3 +11,6 @@ Bugfixes * Fixed crash when coercing ``ManyRelatedManager`` to a string (:ticket:`24352`). * Fixed a bug that prevented migrations from adding a FK constraint for an existing column. (:ticket:`24447`).
tests/schema/models.py +9 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,15 @@ class BookWithM2M(models.Model): apps = new_apps class BookWithoutFK(models.Model): author = models.IntegerField() title = models.CharField(max_length=100, db_index=True) pub_date = models.DateTimeField() class Meta: apps = new_apps class TagThrough(models.Model): book = models.ForeignKey("schema.BookWithM2MThrough") tag = models.ForeignKey("schema.TagM2MTest") Loading
tests/schema/tests.py +34 −2 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ from .fields import CustomManyToManyField, InheritedManyToManyField from .models import (Author, AuthorWithDefaultHeight, AuthorWithM2M, Book, BookWithLongName, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorTag, AuthorWithM2MThrough, AuthorWithEvenLongerName, BookWeak, Note, BookWithO2O) AuthorWithEvenLongerName, BookWeak, Note, BookWithO2O, BookWithoutFK) class SchemaTests(TransactionTestCase): Loading @@ -29,7 +29,7 @@ class SchemaTests(TransactionTestCase): Author, AuthorWithM2M, Book, BookWithLongName, BookWithSlug, BookWithM2M, Tag, TagIndexed, TagM2MTest, TagUniqueRename, UniqueTest, Thing, TagThrough, BookWithM2MThrough, AuthorWithEvenLongerName, BookWeak, BookWithO2O, BookWeak, BookWithO2O, BookWithoutFK, ] # Utility functions Loading Loading @@ -536,6 +536,38 @@ class SchemaTests(TransactionTestCase): else: self.fail("No FK constraint for author_id found") @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support") def test_alter_to_fk(self): """ #24447 - Tests adding a FK constraint for an existing column """ # Create the tables with connection.schema_editor() as editor: editor.create_model(Author) editor.create_model(BookWithoutFK) # Ensure no FK constraint exists constraints = self.get_constraints(BookWithoutFK._meta.db_table) for name, details in constraints.items(): if details['foreign_key']: self.fail('Found an unexpected FK constraint to %s' % details['columns']) new_field = ForeignKey(Author) new_field.set_attributes_from_name("author") with connection.schema_editor() as editor: editor.alter_field( BookWithoutFK, BookWithoutFK._meta.get_field_by_name("author")[0], new_field, strict=True, ) constraints = self.get_constraints(BookWithoutFK._meta.db_table) # Ensure FK constraint exists for name, details in constraints.items(): if details['foreign_key'] and details['columns'] == ["author_id"]: self.assertEqual(details['foreign_key'], ('schema_author', 'id')) break else: self.fail("No FK constraint for author_id found") @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support") def test_alter_o2o_to_fk(self): """ Loading