From bab3ad54ff30848a16f08d72e70d8edbab019a63 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Sun, 13 Oct 2019 21:54:10 -0400 Subject: [PATCH] [3.0.x] Fixed #30868 -- Prevented unnecessary AlterField when renaming a referenced pk. Regression introduced by dcdd219ee1, refs #25817. Thanks Carlos E. C. Leite for the report and Mariusz for the bisect. Backport of 2839659b42ef80038152768b6cedae1016c59d90 from master --- django/db/migrations/autodetector.py | 4 ++++ tests/migrations/test_autodetector.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index 1c40161c7ff..b2db84ffcbd 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -927,6 +927,10 @@ class MigrationAutodetector: if remote_field_name: to_field_rename_key = rename_key + (remote_field_name,) if to_field_rename_key in self.renamed_fields: + # Repoint both model and field name because to_field + # inclusion in ForeignKey.deconstruct() is based on + # both. + new_field.remote_field.model = old_field.remote_field.model new_field.remote_field.field_name = old_field.remote_field.field_name # Handle ForeignObjects which can have multiple from_fields/to_fields. from_fields = getattr(new_field, 'from_fields', None) diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 1d5b8ef4638..633d40a26fa 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -932,6 +932,30 @@ class AutodetectorTests(TestCase): changes, 'app', 0, 1, model_name='bar', old_name='second', new_name='second_renamed', ) + def test_rename_referenced_primary_key(self): + before = [ + ModelState('app', 'Foo', [ + ('id', models.CharField(primary_key=True, serialize=False)), + ]), + ModelState('app', 'Bar', [ + ('id', models.AutoField(primary_key=True)), + ('foo', models.ForeignKey('app.Foo', models.CASCADE)), + ]), + ] + after = [ + ModelState('app', 'Foo', [ + ('renamed_id', models.CharField(primary_key=True, serialize=False)) + ]), + ModelState('app', 'Bar', [ + ('id', models.AutoField(primary_key=True)), + ('foo', models.ForeignKey('app.Foo', models.CASCADE)), + ]), + ] + changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename': True})) + self.assertNumberMigrations(changes, 'app', 1) + self.assertOperationTypes(changes, 'app', 0, ['RenameField']) + self.assertOperationAttributes(changes, 'app', 0, 0, old_name='id', new_name='renamed_id') + def test_rename_field_preserved_db_column(self): """ RenameField is used if a field is renamed and db_column equal to the