From 828082dad954e87d09a99b53424e6faa1860ccc7 Mon Sep 17 00:00:00 2001 From: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:01:23 +0100 Subject: [PATCH] Fixed #34984 -- Skipped GeneratedFields when remaking tables on SQLite. Regression in f333e3513e8bdf5ffeb6eeb63021c230082e6f95.t Co-authored-by: Mariusz Felisiak Co-authored-by: David Sanders --- django/db/backends/sqlite3/schema.py | 3 ++- tests/migrations/test_operations.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index a8200a1a8c..64cf0188d2 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -107,6 +107,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): mapping = { f.column: self.quote_name(f.column) for f in model._meta.local_concrete_fields + if f.generated is False } # This maps field names (not columns) for things like unique_together rename_mapping = {} @@ -163,7 +164,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): # Remove any deleted fields if delete_field: del body[delete_field.name] - del mapping[delete_field.column] + mapping.pop(delete_field.column, None) # Remove any implicit M2M tables if ( delete_field.many_to_many diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 21e8ab069a..7643111c34 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -5801,6 +5801,42 @@ class OperationTests(OperationTestBase): def test_remove_generated_field_virtual(self): self._test_remove_generated_field(db_persist=False) + @skipUnlessDBFeature("supports_stored_generated_columns") + def test_add_field_after_generated_field(self): + app_label = "test_adfagf" + project_state = self.set_up_test_model(app_label) + operation_1 = migrations.AddField( + "Pony", + "generated", + models.GeneratedField( + expression=Value(1), + output_field=models.IntegerField(), + db_persist=True, + ), + ) + operation_2 = migrations.AddField( + "Pony", + "static", + models.IntegerField(default=2), + ) + new_state = project_state.clone() + operation_1.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation_1.database_forwards(app_label, editor, project_state, new_state) + project_state, new_state = new_state, new_state.clone() + pony_old = new_state.apps.get_model(app_label, "Pony").objects.create(weight=20) + self.assertEqual(pony_old.generated, 1) + operation_2.state_forwards(app_label, new_state) + with connection.schema_editor() as editor: + operation_2.database_forwards(app_label, editor, project_state, new_state) + Pony = new_state.apps.get_model(app_label, "Pony") + pony_old = Pony.objects.get(pk=pony_old.pk) + self.assertEqual(pony_old.generated, 1) + self.assertEqual(pony_old.static, 2) + pony_new = Pony.objects.create(weight=20) + self.assertEqual(pony_new.generated, 1) + self.assertEqual(pony_new.static, 2) + class SwappableOperationTests(OperationTestBase): """