Selaa lähdekoodia

Fixed #28541 -- Fixed migrations crash when changing primary key on SQLite.

Ben Cail 1 vuosi sitten
vanhempi
commit
593067a8ee
2 muutettua tiedostoa jossa 44 lisäystä ja 0 poistoa
  1. 8 0
      django/db/backends/sqlite3/schema.py
  2. 36 0
      tests/migrations/test_operations.py

+ 8 - 0
django/db/backends/sqlite3/schema.py

@@ -229,6 +229,14 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
         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)
 

+ 36 - 0
tests/migrations/test_operations.py

@@ -2802,6 +2802,42 @@ class OperationTests(OperationTestBase):
                 (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"