Fixed #34227 -- Fixed QuerySet.select_related() with multi-level FilteredRelation.

This commit is contained in:
朱穆穆 2022-12-29 10:23:46 +08:00 committed by Mariusz Felisiak
parent ef85b6bf0b
commit d3c93cdc59
2 changed files with 28 additions and 1 deletions

View File

@ -1274,6 +1274,9 @@ class SQLCompiler:
if from_obj: if from_obj:
final_field.remote_field.set_cached_value(from_obj, obj) final_field.remote_field.set_cached_value(from_obj, obj)
def local_setter_noop(obj, from_obj):
pass
def remote_setter(name, obj, from_obj): def remote_setter(name, obj, from_obj):
setattr(from_obj, name, obj) setattr(from_obj, name, obj)
@ -1295,7 +1298,11 @@ class SQLCompiler:
"model": model, "model": model,
"field": final_field, "field": final_field,
"reverse": True, "reverse": True,
"local_setter": partial(local_setter, final_field), "local_setter": (
partial(local_setter, final_field)
if len(joins) <= 2
else local_setter_noop
),
"remote_setter": partial(remote_setter, name), "remote_setter": partial(remote_setter, name),
"from_parent": from_parent, "from_parent": from_parent,
} }

View File

@ -164,3 +164,23 @@ class ExistingRelatedInstancesTests(TestCase):
) )
self.assertIs(ps[0], ps[0].pool_1.poolstyle) self.assertIs(ps[0], ps[0].pool_1.poolstyle)
self.assertIs(ps[0], ps[0].pool_2.another_style) self.assertIs(ps[0], ps[0].pool_2.another_style)
def test_multilevel_reverse_fk_cyclic_select_related(self):
with self.assertNumQueries(3):
p = list(
PoolStyle.objects.annotate(
tournament_pool=FilteredRelation("pool__tournament__pool"),
).select_related("tournament_pool", "tournament_pool__tournament")
)
self.assertEqual(p[0].tournament_pool.tournament, p[0].pool.tournament)
def test_multilevel_reverse_fk_select_related(self):
with self.assertNumQueries(2):
p = list(
Tournament.objects.filter(id=self.t2.id)
.annotate(
style=FilteredRelation("pool__another_style"),
)
.select_related("style")
)
self.assertEqual(p[0].style.another_pool, self.p3)