Loading django/db/backends/sqlite3/schema.py +9 −1 Original line number Diff line number Diff line Loading @@ -76,8 +76,16 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 3. copy the data from the old renamed table to the new table 4. delete the "app_model__old" table """ # Self-referential fields must be recreated rather than copied from # the old model to ensure their remote_field.field_name doesn't refer # to an altered field. def is_self_referential(f): return f.is_relation and f.remote_field.model is model # Work out the new fields dict / mapping body = {f.name: f for f in model._meta.local_concrete_fields} body = { f.name: f.clone() if is_self_referential(f) else f for f in model._meta.local_concrete_fields } # Since mapping might mix column names and default values, # its values must be already quoted. mapping = {f.column: self.quote_name(f.column) for f in model._meta.local_concrete_fields} Loading docs/releases/1.9.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -43,3 +43,6 @@ Bugfixes * Fixed a regression with abstract model inheritance and explicit parent links (:ticket:`26413`). * Fixed a migrations crash on SQLite when renaming the primary key of a model containing a ``ForeignKey`` to ``'self'`` (:ticket:`26384`). tests/schema/models.py +5 −0 Original line number Diff line number Diff line Loading @@ -177,3 +177,8 @@ class UniqueTest(models.Model): class Meta: apps = new_apps unique_together = ["year", "slug"] class Node(models.Model): node_id = models.AutoField(primary_key=True) parent = models.ForeignKey('self', models.CASCADE, null=True, blank=True) tests/schema/tests.py +13 −2 Original line number Diff line number Diff line Loading @@ -27,8 +27,8 @@ from .fields import ( from .models import ( Author, AuthorWithDefaultHeight, AuthorWithEvenLongerName, Book, BookForeignObj, BookWeak, BookWithLongName, BookWithO2O, BookWithoutAuthor, BookWithSlug, IntegerPK, Note, NoteRename, Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, UniqueTest, new_apps, BookWithSlug, IntegerPK, Node, Note, NoteRename, Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, UniqueTest, new_apps, ) Loading Loading @@ -1818,3 +1818,14 @@ class SchemaTests(TransactionTestCase): self.get_constraints_for_column(Tag, 'slug'), ['schema_tag_slug_2c418ba3_like', 'schema_tag_slug_key'] ) def test_alter_pk_with_self_referential_field(self): """ Changing the primary key field name of a model with a self-referential foreign key (#26384). """ old_field = Node._meta.get_field('node_id') new_field = AutoField(primary_key=True) new_field.set_attributes_from_name('id') with connection.schema_editor() as editor: editor.alter_field(Node, old_field, new_field) Loading
django/db/backends/sqlite3/schema.py +9 −1 Original line number Diff line number Diff line Loading @@ -76,8 +76,16 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): 3. copy the data from the old renamed table to the new table 4. delete the "app_model__old" table """ # Self-referential fields must be recreated rather than copied from # the old model to ensure their remote_field.field_name doesn't refer # to an altered field. def is_self_referential(f): return f.is_relation and f.remote_field.model is model # Work out the new fields dict / mapping body = {f.name: f for f in model._meta.local_concrete_fields} body = { f.name: f.clone() if is_self_referential(f) else f for f in model._meta.local_concrete_fields } # Since mapping might mix column names and default values, # its values must be already quoted. mapping = {f.column: self.quote_name(f.column) for f in model._meta.local_concrete_fields} Loading
docs/releases/1.9.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -43,3 +43,6 @@ Bugfixes * Fixed a regression with abstract model inheritance and explicit parent links (:ticket:`26413`). * Fixed a migrations crash on SQLite when renaming the primary key of a model containing a ``ForeignKey`` to ``'self'`` (:ticket:`26384`).
tests/schema/models.py +5 −0 Original line number Diff line number Diff line Loading @@ -177,3 +177,8 @@ class UniqueTest(models.Model): class Meta: apps = new_apps unique_together = ["year", "slug"] class Node(models.Model): node_id = models.AutoField(primary_key=True) parent = models.ForeignKey('self', models.CASCADE, null=True, blank=True)
tests/schema/tests.py +13 −2 Original line number Diff line number Diff line Loading @@ -27,8 +27,8 @@ from .fields import ( from .models import ( Author, AuthorWithDefaultHeight, AuthorWithEvenLongerName, Book, BookForeignObj, BookWeak, BookWithLongName, BookWithO2O, BookWithoutAuthor, BookWithSlug, IntegerPK, Note, NoteRename, Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, UniqueTest, new_apps, BookWithSlug, IntegerPK, Node, Note, NoteRename, Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, UniqueTest, new_apps, ) Loading Loading @@ -1818,3 +1818,14 @@ class SchemaTests(TransactionTestCase): self.get_constraints_for_column(Tag, 'slug'), ['schema_tag_slug_2c418ba3_like', 'schema_tag_slug_key'] ) def test_alter_pk_with_self_referential_field(self): """ Changing the primary key field name of a model with a self-referential foreign key (#26384). """ old_field = Node._meta.get_field('node_id') new_field = AutoField(primary_key=True) new_field.set_attributes_from_name('id') with connection.schema_editor() as editor: editor.alter_field(Node, old_field, new_field)