Refs #27666 -- Ensured relationship consistency on delayed reloads.
Delayed reloads of state models broke identity based relationships between direct and non-direct ancestors. Basing models.Options related objects map of model labels instead of their identity ensured relationship consistency is maintained. Refs #30966. Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
This commit is contained in:
parent
e03eb8db93
commit
1d16c5d562
|
@ -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().
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue