diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py index 495714a894e..c5b428fc678 100644 --- a/django/db/backends/sqlite3/schema.py +++ b/django/db/backends/sqlite3/schema.py @@ -150,6 +150,9 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): body.pop(old_field.name, None) mapping.pop(old_field.column, None) body[new_field.name] = new_field + rename_mapping[old_field.name] = new_field.name + if new_field.generated: + continue if old_field.null and not new_field.null: if new_field.db_default is NOT_PROVIDED: default = self.prepare_default(self.effective_default(new_field)) @@ -162,7 +165,6 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): mapping[new_field.column] = case_sql else: mapping[new_field.column] = self.quote_name(old_field.column) - rename_mapping[old_field.name] = new_field.name # Remove any deleted fields if delete_field: del body[delete_field.name] diff --git a/docs/releases/5.0.5.txt b/docs/releases/5.0.5.txt index f8b66a59992..788753c8263 100644 --- a/docs/releases/5.0.5.txt +++ b/docs/releases/5.0.5.txt @@ -16,3 +16,7 @@ Bugfixes * Fixed a compatibility issue encountered in Python 3.11.9+ and 3.12.3+ when validating email max line lengths with content decoded using the ``surrogateescape`` error handling scheme (:ticket:`35361`). + +* Fixed a bug in Django 5.0 that caused a crash when applying migrations + including alterations to ``GeneratedField`` such as setting ``db_index=True`` + on SQLite (:ticket:`35373`). diff --git a/tests/schema/tests.py b/tests/schema/tests.py index ff126d446a6..3a2947cf434 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -928,6 +928,39 @@ class SchemaTests(TransactionTestCase): self.assertEqual(obj.generated, "foo%") self.assertIs(obj.contains_foo, True) + @isolate_apps("schema") + @skipUnlessDBFeature("supports_stored_generated_columns") + def test_alter_generated_field(self): + class GeneratedFieldIndexedModel(Model): + number = IntegerField(default=1) + generated = GeneratedField( + expression=F("number"), + db_persist=True, + output_field=IntegerField(), + ) + + class Meta: + app_label = "schema" + + with connection.schema_editor() as editor: + editor.create_model(GeneratedFieldIndexedModel) + + old_field = GeneratedFieldIndexedModel._meta.get_field("generated") + new_field = GeneratedField( + expression=F("number"), + db_persist=True, + db_index=True, + output_field=IntegerField(), + ) + new_field.contribute_to_class(GeneratedFieldIndexedModel, "generated") + + with connection.schema_editor() as editor: + editor.alter_field(GeneratedFieldIndexedModel, old_field, new_field) + + self.assertIn( + "generated", self.get_indexes(GeneratedFieldIndexedModel._meta.db_table) + ) + @isolate_apps("schema") def test_add_auto_field(self): class AddAutoFieldModel(Model):