-
Notifications
You must be signed in to change notification settings - Fork 823
Is there a good way to ask if a quey contains a certain field? #348
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
Comments
I am doing something similar in a related project. I think it's something that's probably better handled outside the resolve function. You do get the info argument passed to resolve_viewer, but to my knowledge, it's not easy to parse and would be way too fragile as it may change depending on the query. A better approach could be to return a lazy loading object that resolves the viewer from DB when a non-id field is accessed. You would return ViewerProxy(user_id, UserClass) instead of the real User. When the underlying graphene code tries to get friends from your user object, the "prefetch" would trigger.
Another thing that comes to mind: I don't know what you're setup is for authentication, but most likely, the viewer has already been queried as part of your authentication/session logic, so you probably already made a query to the db by the time you hit the resolve_viewer in which case, you'd be returning g.user (for flask) or request.user for django, so I don't know if you'd be gaining anything from this approach. |
Hey @yfilali, Say my query is:
If I use an object proxy then, given a user, if you query for |
Not so! Notice that I have a test for that "and isinstance(self.wrapped, type):" If the wrapped object is a type, we query and convert it to an instance. This makes sure we only query once. Edit: sorry, I think I misunderstood at first. See how I do it here: RelationshipResultList |
once per type... if |
Maybe this describes the problem better: |
Yes, in your case, the sequence would go something like this:
|
Here is the same thing in code. Does something like this work for you?
|
I don't think I follow this solution ...
The |
@ekampf you can do something like the following (extracted from a PR that optimizes queries in graphene-django). def get_type(_type):
if isinstance(_type, (GraphQLList, GraphQLNonNull)):
return get_type(_type.of_type)
return _type
def get_fields(info):
field_asts = info.field_asts[0].selection_set.selections
_type = get_type(info.return_type)
for field_ast in field_asts:
field_name = field_ast.name.value
yield field_name
# You can also do:
# field_def = get_field_def(info.schema, _type, field_ast)
# yield field_def.resolver # This will get the field resolver |
Wow, that's a much less flawed approach than mine! @syrusakbary What about spreading fragments like per @ekampf's initial question? something like this? def get_type(_type):
if isinstance(_type, (GraphQLList, GraphQLNonNull)):
return get_type(_type.of_type)
return _type
def get_fields(info):
fragments = info.fragments
field_asts = info.field_asts[0].selection_set.selections
_type = get_type(info.return_type)
for field_ast in field_asts:
field_name = field_ast.name.value
if isinstance(field_ast, FragmentSpread):
for field in fragments[field_name].selection_set.selections:
yield field.name.value
continue
yield field_name |
Ended up with the following introspection code (based on the code above, but allows looking several levels deep into the query):
|
Here's a function that gives you the names of all selected fields: #57 (comment) Convert the list to |
for example:
I want
resolve_viewer
to be able to ask if we're querying forfriends
underviewer
so it can do some prefetching...Also needs to support fragments because the query above could be written as:
The text was updated successfully, but these errors were encountered: