Skip to content

Commit

Permalink
Allow for hints with same value on multiple different resolvers of a …
Browse files Browse the repository at this point in the history
…given DjangoObjectType.
  • Loading branch information
felixmeziere committed Sep 21, 2021
1 parent 2fd8af4 commit f5fbc23
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
4 changes: 3 additions & 1 deletion graphene_django_optimizer/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ def _add_optimization_hints(self, source, target):
if source:
if not is_iterable(source):
source = (source,)
target += source
target += [
source_item for source_item in source if source_item not in target
]

def _get_name_from_resolver(self, resolver):
optimization_hints = self._get_optimization_hints(resolver)
Expand Down
18 changes: 18 additions & 0 deletions tests/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class ItemInterface(graphene.Interface):
"tests.schema.ItemType",
name=graphene.String(required=True),
)
aux_filtered_children = graphene.List(
"tests.schema.ItemType",
name=graphene.String(required=True),
)
children_custom_filtered = gql_optimizer.field(
ConnectionField("tests.schema.ItemConnection", filter_input=ItemFilterInput()),
prefetch_related=_prefetch_children,
Expand Down Expand Up @@ -82,6 +86,20 @@ def resolve_aux_children_names(root, info):
def resolve_filtered_children(root, info, name):
return getattr(root, "gql_filtered_children_" + name)

@gql_optimizer.resolver_hints(
prefetch_related=lambda info, name: Prefetch(
"children",
queryset=gql_optimizer.query(
Item.objects.filter(name=f"some_prefix {name}"), info
),
# Different queryset than resolve_filtered_children but same to_attr, on purpose
# to check equality of Prefetch is based only on to_attr attribute, as it is implemented in Django.
to_attr="gql_filtered_children_" + name,
),
)
def resolve_aux_filtered_children(root, info, name):
return getattr(root, "gql_filtered_children_" + name)

def resolve_children_custom_filtered(root, info, *_args):
return getattr(root, "gql_custom_filtered_children")

Expand Down
31 changes: 31 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,34 @@ def test_should_only_use_the_only_and_not_select_related():
items = gql_optimizer.query(qs, info)
optimized_items = qs.only("id", "name")
assert_query_equality(items, optimized_items)


@pytest.mark.django_db
def test_should_accept_two_hints_with_same_prefetch_to_attr_and_keep_one_of_them():
info = create_resolve_info(
schema,
"""
query {
items(name: "foo") {
filteredChildren(name: "bar") {
id
name
}
auxFilteredChildren(name: "bar") { # Same name to generate Prefetch with same to_attr
id
name
}
}
}
""",
)
qs = Item.objects.filter(name="foo")
items = gql_optimizer.query(qs, info)
optimized_items = qs.prefetch_related(
Prefetch(
"children",
queryset=Item.objects.filter(name="bar").only("id", "name"),
to_attr="gql_filtered_children_foo",
)
)
assert_query_equality(items, optimized_items)

0 comments on commit f5fbc23

Please sign in to comment.