From 593067a8ee43e2167c5ffc92e3cc3c5e40ec4aa4 Mon Sep 17 00:00:00 2001 From: Ben Cail Date: Thu, 7 Mar 2024 15:34:16 -0500 Subject: [PATCH] Fixed #28541 -- Fixed migrations crash when changing primary key on SQLite. --- django/db/backends/sqlite3/schema.py | 8 +++++++ tests/migrations/test_operations.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index d27a8bbd65d7..495714a894ea 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -229,6 +229,14 @@ def is_self_referential(f): body_copy["__module__"] = model.__module__ new_model = type("New%s" % model._meta.object_name, model.__bases__, body_copy) + # Remove the automatically recreated default primary key, if it has + # been deleted. + if delete_field and delete_field.attname == new_model._meta.pk.attname: + auto_pk = new_model._meta.pk + delattr(new_model, auto_pk.attname) + new_model._meta.local_fields.remove(auto_pk) + new_model.pk = None + # Create a new table with the updated schema. self.create_model(new_model) diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 3845381454df..b058543801f7 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -2802,6 +2802,42 @@ def assertIdTypeEqualsMTIFkType(): (f"{app_label}_pony", "id"), ) + def test_alter_id_pk_to_uuid_pk(self): + app_label = "test_alidpktuuidpk" + project_state = self.set_up_test_model(app_label) + new_state = project_state.clone() + # Add UUID field. + operation = migrations.AddField("Pony", "uuid", models.UUIDField()) + operation.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation.database_forwards(app_label, editor, project_state, new_state) + # Remove ID. + project_state = new_state + new_state = new_state.clone() + operation = migrations.RemoveField("Pony", "id") + operation.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation.database_forwards(app_label, editor, project_state, new_state) + self.assertColumnNotExists(f"{app_label}_pony", "id") + # Rename to ID. + project_state = new_state + new_state = new_state.clone() + operation = migrations.RenameField("Pony", "uuid", "id") + operation.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation.database_forwards(app_label, editor, project_state, new_state) + self.assertColumnNotExists(f"{app_label}_pony", "uuid") + self.assertColumnExists(f"{app_label}_pony", "id") + # Change to a primary key. + project_state = new_state + new_state = new_state.clone() + operation = migrations.AlterField( + "Pony", "id", models.UUIDField(primary_key=True) + ) + operation.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation.database_forwards(app_label, editor, project_state, new_state) + @skipUnlessDBFeature("supports_foreign_keys") def test_alter_field_reloads_state_on_fk_with_to_field_target_type_change(self): app_label = "test_alflrsfkwtflttc"