Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve a Field nested in another Type using Graphene GraphQL?

I have 3 files: authors.py, posts.py and schema.py.

Posts have one Author and the Query is built in the schema file.

I'm trying to resolve Author from inside Post without declaring a resolver function in Post, since Author already has a resolver function for itself declared. The following code works, but I have to reference resolve_author from inside the Post type and it doesn't seem right. I think Graphene should pass the parent param directly to Author, no?

If I don't set a resolver for author in the Post type, it simply returns null.

schema.py

import graphene
from graphql_api import posts, authors


class Query(posts.Query, authors.Query):
    pass


schema = graphene.Schema(query=Query)

authors.py

from graphene import ObjectType, String, Field


class Author(ObjectType):
    id = ID()
    name = String()


class Query(ObjectType):
    author = Field(Author)

    def resolve_author(parent, info):
        return {
            'id': '123',
            'name': 'Grizzly Bear',
            'avatar': '#984321'
        }

posts.py

from graphene import ObjectType, String, Field
from graphql_api import authors


class Post(ObjectType):
    content = String()
    author = Field(authors.Author)

    def resolve_author(parent, info):
        # I'm doing like this and it works, but it seems wrong. 
        # I think Graphene should be able to use my resolver 
        # from the Author automatically...
        return authors.Query.resolve_author(parent,
                                            info, id=parent['authorId'])


class Query(ObjectType):
    post = Field(Post)

    def resolve_post(parent, info):
        return {
            'content': 'A title',
            'authorId': '123',
        }
like image 755
jpenna Avatar asked Aug 07 '19 10:08

jpenna


1 Answers

Query.resolve_author wouldn't be called because there is no relation between it and Post object.

I suggest something like:

from graphene import ObjectType, String, Field
from graphql_api import authors


class Post(ObjectType):
    content = String()
    author = Field(authors.Author)

    def resolve_author(self, info):
        # author_utils.get_author returns complete object that will be passed into Author's object resolvers (if some fields are missing)
        # I suggest returning here an object from database so author resolver would extract another fields inside
        # But it may be just an id that will be passed in Author resolvers as first arguments
        return author_utils.get_author(post_id=self.id)


class Query(ObjectType):
    post = Field(Post)

    def resolve_post(parent, info):
        # Here you shouldn't author_id as it's not defined in type 
        return {
            'content': 'A title',
        }

And Author (assume author_utils.get_author just returns an id):

class Author(ObjectType):
    id = ID()
    name = String()

    def resolve_id(id, info):
        # root here is what resolve_author returned in post. Be careful, it also will be called if id is missing after Query.resolve_author
        return id

    def resolve_name(id, info):
        # same as resolve_id
        return utils.get_name_by_id(id)
like image 130
donnyyy Avatar answered Sep 23 '22 07:09

donnyyy