diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index d8fcb5807d..e79e745978 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -468,12 +468,18 @@ class MigrationAutodetector: rem_model_fields_def = self.only_relation_agnostic_fields(rem_model_state.fields) if model_fields_def == rem_model_fields_def: if self.questioner.ask_rename_model(rem_model_state, model_state): + model_opts = self.new_apps.get_model(app_label, model_name)._meta + dependencies = [] + for field in model_opts.get_fields(): + if field.is_relation: + dependencies.extend(self._get_dependencies_for_foreign_key(field)) self.add_operation( app_label, operations.RenameModel( old_name=rem_model_state.name, new_name=model_state.name, - ) + ), + dependencies=dependencies, ) self.renamed_models[app_label, model_name] = rem_model_name renamed_models_rel_key = '%s.%s' % (rem_model_state.app_label, rem_model_state.name) diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 997c81f29e..74961048fb 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -901,6 +901,37 @@ class AutodetectorTests(TestCase): self.assertOperationTypes(changes, "testapp", 0, ["RenameModel"]) self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="EntityB", new_name="RenamedEntityB") + def test_rename_model_reverse_relation_dependencies(self): + """ + The migration to rename a model pointed to by a foreign key in another + app must run after the other app's migration that adds the foreign key + with model's original name. Therefore, the renaming migration has a + dependency on that other migration. + """ + before = [ + ModelState('testapp', 'EntityA', [ + ('id', models.AutoField(primary_key=True)), + ]), + ModelState('otherapp', 'EntityB', [ + ('id', models.AutoField(primary_key=True)), + ('entity_a', models.ForeignKey('testapp.EntityA', models.CASCADE)), + ]), + ] + after = [ + ModelState('testapp', 'RenamedEntityA', [ + ('id', models.AutoField(primary_key=True)), + ]), + ModelState('otherapp', 'EntityB', [ + ('id', models.AutoField(primary_key=True)), + ('entity_a', models.ForeignKey('testapp.RenamedEntityA', models.CASCADE)), + ]), + ] + changes = self.get_changes(before, after, MigrationQuestioner({'ask_rename_model': True})) + self.assertNumberMigrations(changes, 'testapp', 1) + self.assertMigrationDependencies(changes, 'testapp', 0, [('otherapp', '__first__')]) + self.assertOperationTypes(changes, 'testapp', 0, ['RenameModel']) + self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name='EntityA', new_name='RenamedEntityA') + def test_fk_dependency(self): """Having a ForeignKey automatically adds a dependency.""" # Note that testapp (author) has no dependencies,