diff --git a/django/db/models/options.py b/django/db/models/options.py index f027a74976..0e28b6812a 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -698,7 +698,8 @@ class Options: ) for f in fields_with_relations: if not isinstance(f.remote_field.model, str): - related_objects_graph[f.remote_field.model._meta.concrete_model._meta].append(f) + remote_label = f.remote_field.model._meta.concrete_model._meta.label + related_objects_graph[remote_label].append(f) for model in all_models: # Set the relation_tree using the internal __dict__. In this way @@ -706,7 +707,7 @@ class Options: # __dict__ takes precedence over a data descriptor (such as # @cached_property). This means that the _meta._relation_tree is # only called if related_objects is not in __dict__. - related_objects = related_objects_graph[model._meta.concrete_model._meta] + related_objects = related_objects_graph[model._meta.concrete_model._meta.label] model._meta.__dict__['_relation_tree'] = related_objects # It seems it is possible that self is not in all_models, so guard # against that with default for get(). diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index ef198eb0b6..44d4cdf268 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -532,6 +532,30 @@ class StateTests(SimpleTestCase): project_state.add_model(ModelState.from_model(B)) self.assertEqual(len(project_state.apps.get_models()), 2) + def test_reload_model_relationship_consistency(self): + project_state = ProjectState() + project_state.add_model(ModelState('migrations', 'A', [])) + project_state.add_model(ModelState('migrations', 'B', [ + ('a', models.ForeignKey('A', models.CASCADE)), + ])) + project_state.add_model(ModelState('migrations', 'C', [ + ('b', models.ForeignKey('B', models.CASCADE)), + ])) + A = project_state.apps.get_model('migrations.A') + B = project_state.apps.get_model('migrations.B') + C = project_state.apps.get_model('migrations.C') + self.assertEqual([r.related_model for r in A._meta.related_objects], [B]) + self.assertEqual([r.related_model for r in B._meta.related_objects], [C]) + self.assertEqual([r.related_model for r in C._meta.related_objects], []) + + project_state.reload_model('migrations', 'a', delay=True) + A = project_state.apps.get_model('migrations.A') + B = project_state.apps.get_model('migrations.B') + C = project_state.apps.get_model('migrations.C') + self.assertEqual([r.related_model for r in A._meta.related_objects], [B]) + self.assertEqual([r.related_model for r in B._meta.related_objects], [C]) + self.assertEqual([r.related_model for r in C._meta.related_objects], []) + def test_add_relations(self): """ #24573 - Adding relations to existing models should reload the