Skip to content
Snippets Groups Projects
Unverified Commit 76465dc3 authored by Felix Meziere's avatar Felix Meziere Committed by GitHub
Browse files

Allow for hints with same value on multiple different resolvers of a given DjangoObjectType. (#76)

parent 56f38149
No related branches found
No related tags found
No related merge requests found
...@@ -269,7 +269,9 @@ class QueryOptimizer(object): ...@@ -269,7 +269,9 @@ class QueryOptimizer(object):
if source: if source:
if not is_iterable(source): if not is_iterable(source):
source = (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): def _get_name_from_resolver(self, resolver):
optimization_hints = self._get_optimization_hints(resolver) optimization_hints = self._get_optimization_hints(resolver)
......
...@@ -52,6 +52,10 @@ class ItemInterface(graphene.Interface): ...@@ -52,6 +52,10 @@ class ItemInterface(graphene.Interface):
"tests.schema.ItemType", "tests.schema.ItemType",
name=graphene.String(required=True), name=graphene.String(required=True),
) )
aux_filtered_children = graphene.List(
"tests.schema.ItemType",
name=graphene.String(required=True),
)
children_custom_filtered = gql_optimizer.field( children_custom_filtered = gql_optimizer.field(
ConnectionField("tests.schema.ItemConnection", filter_input=ItemFilterInput()), ConnectionField("tests.schema.ItemConnection", filter_input=ItemFilterInput()),
prefetch_related=_prefetch_children, prefetch_related=_prefetch_children,
...@@ -82,6 +86,20 @@ class ItemInterface(graphene.Interface): ...@@ -82,6 +86,20 @@ class ItemInterface(graphene.Interface):
def resolve_filtered_children(root, info, name): def resolve_filtered_children(root, info, name):
return getattr(root, "gql_filtered_children_" + 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): def resolve_children_custom_filtered(root, info, *_args):
return getattr(root, "gql_custom_filtered_children") return getattr(root, "gql_custom_filtered_children")
......
...@@ -585,3 +585,34 @@ def test_should_only_use_the_only_and_not_select_related(): ...@@ -585,3 +585,34 @@ def test_should_only_use_the_only_and_not_select_related():
items = gql_optimizer.query(qs, info) items = gql_optimizer.query(qs, info)
optimized_items = qs.only("id", "name") optimized_items = qs.only("id", "name")
assert_query_equality(items, optimized_items) 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% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment