Skip to content

Commit 76465dc

Browse files
authored
Allow for hints with same value on multiple different resolvers of a given DjangoObjectType. (#76)
1 parent 56f3814 commit 76465dc

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

graphene_django_optimizer/query.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,9 @@ def _add_optimization_hints(self, source, target):
269269
if source:
270270
if not is_iterable(source):
271271
source = (source,)
272-
target += source
272+
target += [
273+
source_item for source_item in source if source_item not in target
274+
]
273275

274276
def _get_name_from_resolver(self, resolver):
275277
optimization_hints = self._get_optimization_hints(resolver)

tests/schema.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class ItemInterface(graphene.Interface):
5252
"tests.schema.ItemType",
5353
name=graphene.String(required=True),
5454
)
55+
aux_filtered_children = graphene.List(
56+
"tests.schema.ItemType",
57+
name=graphene.String(required=True),
58+
)
5559
children_custom_filtered = gql_optimizer.field(
5660
ConnectionField("tests.schema.ItemConnection", filter_input=ItemFilterInput()),
5761
prefetch_related=_prefetch_children,
@@ -82,6 +86,20 @@ def resolve_aux_children_names(root, info):
8286
def resolve_filtered_children(root, info, name):
8387
return getattr(root, "gql_filtered_children_" + name)
8488

89+
@gql_optimizer.resolver_hints(
90+
prefetch_related=lambda info, name: Prefetch(
91+
"children",
92+
queryset=gql_optimizer.query(
93+
Item.objects.filter(name=f"some_prefix {name}"), info
94+
),
95+
# Different queryset than resolve_filtered_children but same to_attr, on purpose
96+
# to check equality of Prefetch is based only on to_attr attribute, as it is implemented in Django.
97+
to_attr="gql_filtered_children_" + name,
98+
),
99+
)
100+
def resolve_aux_filtered_children(root, info, name):
101+
return getattr(root, "gql_filtered_children_" + name)
102+
85103
def resolve_children_custom_filtered(root, info, *_args):
86104
return getattr(root, "gql_custom_filtered_children")
87105

tests/test_query.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,34 @@ def test_should_only_use_the_only_and_not_select_related():
585585
items = gql_optimizer.query(qs, info)
586586
optimized_items = qs.only("id", "name")
587587
assert_query_equality(items, optimized_items)
588+
589+
590+
@pytest.mark.django_db
591+
def test_should_accept_two_hints_with_same_prefetch_to_attr_and_keep_one_of_them():
592+
info = create_resolve_info(
593+
schema,
594+
"""
595+
query {
596+
items(name: "foo") {
597+
filteredChildren(name: "bar") {
598+
id
599+
name
600+
}
601+
auxFilteredChildren(name: "bar") { # Same name to generate Prefetch with same to_attr
602+
id
603+
name
604+
}
605+
}
606+
}
607+
""",
608+
)
609+
qs = Item.objects.filter(name="foo")
610+
items = gql_optimizer.query(qs, info)
611+
optimized_items = qs.prefetch_related(
612+
Prefetch(
613+
"children",
614+
queryset=Item.objects.filter(name="bar").only("id", "name"),
615+
to_attr="gql_filtered_children_foo",
616+
)
617+
)
618+
assert_query_equality(items, optimized_items)

0 commit comments

Comments
 (0)