~turminal/django

ed87af32662bf7a3829e679831e6e019b9d85112 — Alex Hill 8 years ago 026574e
[1.9.x] Fixed #26384 -- Fixed renaming the PK on a model with a self-referential FK on SQLite.

Backport of 4b2cf1cd27587a30b3b081091627d7ee13141afe from master
M django/db/backends/sqlite3/schema.py => django/db/backends/sqlite3/schema.py +9 -1
@@ 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}

M docs/releases/1.9.5.txt => docs/releases/1.9.5.txt +3 -0
@@ 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`).

M tests/schema/models.py => tests/schema/models.py +5 -0
@@ 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)

M tests/schema/tests.py => tests/schema/tests.py +13 -2
@@ 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,
)




@@ 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)