mirror of https://github.com/django/django.git
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:
|
for f in fields_with_relations:
|
||||||
if not isinstance(f.remote_field.model, str):
|
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:
|
for model in all_models:
|
||||||
# Set the relation_tree using the internal __dict__. In this way
|
# 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
|
# __dict__ takes precedence over a data descriptor (such as
|
||||||
# @cached_property). This means that the _meta._relation_tree is
|
# @cached_property). This means that the _meta._relation_tree is
|
||||||
# only called if related_objects is not in __dict__.
|
# 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
|
model._meta.__dict__['_relation_tree'] = related_objects
|
||||||
# It seems it is possible that self is not in all_models, so guard
|
# It seems it is possible that self is not in all_models, so guard
|
||||||
# against that with default for get().
|
# against that with default for get().
|
||||||
|
|
|
@ -532,6 +532,30 @@ class StateTests(SimpleTestCase):
|
||||||
project_state.add_model(ModelState.from_model(B))
|
project_state.add_model(ModelState.from_model(B))
|
||||||
self.assertEqual(len(project_state.apps.get_models()), 2)
|
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):
|
def test_add_relations(self):
|
||||||
"""
|
"""
|
||||||
#24573 - Adding relations to existing models should reload the
|
#24573 - Adding relations to existing models should reload the
|
||||||
|
|
Loading…
Reference in New Issue