Fix migration dependencies when altering field to ForeignKey

Ensure that altering a field to a ForeignKey adds a migration
dependency on the related model, preventing unresolved model errors.
This addresses confusion when changing a UUIDField to a FK (#) and
aligns migration behavior with user expectations.
This commit is contained in:
utkarsh.arya@zomato.com 2025-11-15 22:58:34 +00:00
parent 003bb34b21
commit 32994bd371
2 changed files with 31 additions and 1 deletions

View file

@ -963,6 +963,10 @@ class MigrationAutodetector:
preserve_default = False
else:
field = new_field
# Handle dependencies for fields that are being altered to/from ForeignKeys
dependencies = []
if new_field.remote_field and new_field.remote_field.model:
dependencies.extend(self._get_dependencies_for_foreign_key(new_field))
self.add_operation(
app_label,
operations.AlterField(
@ -970,7 +974,8 @@ class MigrationAutodetector:
name=field_name,
field=field,
preserve_default=preserve_default,
)
),
dependencies=dependencies,
)
else:
# We cannot alter between m2m and concrete fields

View file

@ -366,6 +366,16 @@ class AutodetectorTests(TestCase):
("writer", models.ForeignKey("testapp.Writer", models.CASCADE)),
("title", models.CharField(max_length=200)),
])
book_with_uuid_author = ModelState("otherapp", "Book", [
("id", models.AutoField(primary_key=True)),
("author_id", models.UUIDField(null=True, blank=True)),
("title", models.CharField(max_length=200)),
])
book_with_fk_author = ModelState("otherapp", "Book", [
("id", models.AutoField(primary_key=True)),
("author_id", models.ForeignKey("testapp.Author", models.SET_NULL, null=True, blank=True)),
("title", models.CharField(max_length=200)),
])
book_with_multiple_authors = ModelState("otherapp", "Book", [
("id", models.AutoField(primary_key=True)),
("authors", models.ManyToManyField("testapp.Author")),
@ -821,6 +831,21 @@ class AutodetectorTests(TestCase):
self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=False)
self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default="Some Name")
def test_alter_field_to_fk_dependency(self):
"""
Changing a field to a ForeignKey should add a dependency on the
related model.
"""
changes = self.get_changes(
[self.author_name, self.book_with_uuid_author],
[self.author_name, self.book_with_fk_author]
)
# Right number/type of migrations?
self.assertNumberMigrations(changes, 'otherapp', 1)
self.assertOperationTypes(changes, 'otherapp', 0, ["AlterField"])
self.assertOperationAttributes(changes, "otherapp", 0, 0, name="author_id")
self.assertMigrationDependencies(changes, 'otherapp', 0, [("testapp", "__first__")])
def test_rename_field(self):
"""Tests autodetection of renamed fields."""
changes = self.get_changes(