From 48382a2ff63a974f92bf5c959885947211e3642c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Pe=C4=8Dar?= Date: Thu, 13 Jun 2024 16:41:50 +0200 Subject: [PATCH] [5.1.x] Fixed #34881 -- Fixed a crash when renaming a model with multiple ManyToManyField.through references on SQLite. Thank you to dennisvang for the report and Jase Hackman for the test. Co-authored-by: Jase Hackman Backport of e99187e5c94516ee35f37cc41a36d906b395808d from main. --- django/db/migrations/operations/models.py | 2 +- tests/migrations/test_operations.py | 83 +++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index 34b14107a7e..9aad9c809ee 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -460,11 +460,11 @@ class RenameModel(ModelOperation): model = new_model related_key = (app_label, self.new_name_lower) else: - model = related_object.related_model related_key = ( related_object.related_model._meta.app_label, related_object.related_model._meta.model_name, ) + model = to_state.apps.get_model(*related_key) to_field = to_state.apps.get_model(*related_key)._meta.get_field( related_object.field.name ) diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index d59548f7af5..f1e860493e9 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1345,6 +1345,89 @@ class OperationTests(OperationTestBase): ponyrider = PonyRider.objects.create() ponyrider.riders.add(jockey) + def test_rename_m2m_field_with_2_references(self): + app_label = "test_rename_multiple_references" + project_state = self.apply_operations( + app_label, + ProjectState(), + operations=[ + migrations.CreateModel( + name="Person", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name="Relation", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "child", + models.ForeignKey( + on_delete=models.CASCADE, + related_name="relations_as_child", + to="test_rename_multiple_references.person", + ), + ), + ( + "parent", + models.ForeignKey( + on_delete=models.CASCADE, + related_name="relations_as_parent", + to="test_rename_multiple_references.person", + ), + ), + ], + ), + migrations.AddField( + model_name="person", + name="parents_or_children", + field=models.ManyToManyField( + blank=True, + through="test_rename_multiple_references.Relation", + to="test_rename_multiple_references.person", + ), + ), + ], + ) + Person = project_state.apps.get_model(app_label, "Person") + Relation = project_state.apps.get_model(app_label, "Relation") + + person1 = Person.objects.create(name="John Doe") + person2 = Person.objects.create(name="Jane Smith") + Relation.objects.create(child=person2, parent=person1) + + self.assertTableExists(app_label + "_person") + self.assertTableNotExists(app_label + "_personfoo") + + self.apply_operations( + app_label, + project_state, + operations=[ + migrations.RenameModel(old_name="Person", new_name="PersonFoo"), + ], + ) + + self.assertTableNotExists(app_label + "_person") + self.assertTableExists(app_label + "_personfoo") + def test_add_field(self): """ Tests the AddField operation.