-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gql function should accept additional DocumentNode args #414
Comments
You could use the DSL module to compose queries dynamically. |
Thanks, @leszekhanusz. I don’t really want to drop SDL though. Being able to directly copy query strings from a playground environment, for instance, is very useful. What do you think about incorporating features from graphql-tag into the |
It's better not to mix different goals in the same method. If I understand correctly you would like to merge queries like described in that stackoverflow question. So another method would be preferable, with a signature looking like this: def merge(*documents: DocumentNode) -> DocumentNode: |
My goal is to define reusable fragments, not to merge queries. This is a common workflow with graphql-tag: https://github.com/apollographql/graphql-tag#fragments |
One way to do this would be to concatenate the strings: from gql import gql
from graphql import print_ast
userFragment = """
fragment User_user on User {
firstName
lastName
}
"""
query = gql(
"""
{
user(id: 5) {
...User_user
}
}
"""
+ userFragment
)
print(print_ast(query)) |
Yes, that would work, and actually the graphql-tag interface supports both Its not just a question of this, though. The graphql-tag implementation does other things to aid composition, like deduplicating fragments. This is useful for common fragments like This composition flow is very well-established in the Apollo/JS world. I'm not trying to invent anything here, I'm simply proposing including this functionality because it's a useful approach in my experience. Specifically, I'm proposing a rough port of this code: https://github.com/apollographql/graphql-tag/blob/main/src/index.ts#L114 I'll just close this thread if there's no interest here, however. Thanks! |
You can make such a method yourself with two lines of code: from gql import gql as _gql
from graphql import print_ast, DocumentNode
def gql(*args):
texts = [print_ast(arg) if isinstance(arg, DocumentNode) else arg for arg in args]
return _gql("\n".join(texts))
userFragment = gql(
"""
fragment User_user on User {
firstName
lastName
}
"""
)
query = gql(
userFragment,
"""
{
user(id: 5) {
...User_user
}
}
""",
)
print(print_ast(query)) |
The above example only solves for concatenating additional I've explained this more than once above though, and there's clearly no interest in expanding the scope of this project in this direction. So I'll leave it at that. |
Alright, so your main problem is not related to accepting more args to the gql method but instead is to prevent gql to make documents which are invalid according to the GraphQL spec because they contains the same fragment definition multiple times. What you would like is that: gql("""
query {
...SomeFragment
}
fragment SomeFragment on SomeResource {
field
}
fragment SomeFragment on SomeResource {
field
}""") would make a document with the second fragment definition ignored:
as was explained in graphql-tag issue #27 You have to understand that the gql method in I'm not sure if this should do the trick: from gql import gql as _gql
from typing import Tuple
from graphql import print_ast, DocumentNode, FragmentDefinitionNode, DefinitionNode
def deduplicate_fragments(
definitions: Tuple[DefinitionNode, ...]
) -> Tuple[DefinitionNode]:
fragment_names = []
dedup_definitions = []
for definition in definitions:
if isinstance(definition, FragmentDefinitionNode):
fragment_name = definition.name.value
if fragment_name not in fragment_names:
fragment_names.append(fragment_name)
dedup_definitions.append(definition)
else:
dedup_definitions.append(definition)
return tuple(dedup_definitions)
def gql(*args):
texts = [print_ast(arg) if isinstance(arg, DocumentNode) else arg for arg in args]
document = _gql("\n".join(texts))
document.definitions = deduplicate_fragments(document.definitions)
return document
userFragment = gql(
"""
fragment User_user on User {
firstName
lastName
}
"""
)
query = gql(
userFragment,
userFragment,
"""
{
user(id: 5) {
...User_user
}
}
""",
)
print(print_ast(query)) |
I've already ported the relevant |
Could we make this a first class citizen? I had the same exact problem. |
I'd like to use the
gql()
function in a way that's similar to the common JS/TS pattern, where fragments can be nested to construct queries in a modular fashion.In other words, I'm looking for a signature like this:
I also would like the functionality from JS/TS which deduplicates fragments from the AST, so this is not a bother when building queries with common fragments like
pageInfo
.Is such functionality already present and I'm missing it? I've already got part of this working, and I'd be happy to contribute the change as well. But if it's already there then I don't want to reinvent the wheel.
The text was updated successfully, but these errors were encountered: