Graphene: Document how to implement Connection fields and pagination

Created on 4 Jan 2019  路  5Comments  路  Source: graphql-python/graphene

From the documentation on relay Connection, there is an example on how to define a connection object type, but in the part that shows how to define a connection field, it's not clear what should the resolver return. The example only show an empty list returned. What type of object is a connection resolver supposed to return? Could you show a concrete example?

Also the sentence in that paragraph is not clear:

You can create connection fields in any Connection, in case any ObjectType that implements Node will have a default Connection.

What does this sentence mean?

wontfix 馃摉 documentation

Most helpful comment

Agree that it's a huge trial and error effort to understand this lib. My understanding is that pagination is implemented on the edges, you appear to be trying to implement it on the root node. ie I think:
things(first:1) {edges{node{name}}}
should be:
things{edges(first:1){node{name}}}
This keeps it clean when you want to filter things, then paginate the results ie:

things(name:$name,type:$type)
      { edges(first:$limit) {
         node{
           name
         }
       }
    }

That is the benefit that you get from having the tedious amount of boilerplate in your queries.

All 5 comments

What I found out:

The following worked to define a List field

class Thing(SQLAlchemyObjectType):
    class Meta:
        model = models.Thing # sqlalchemy model

things = graphene.List(ThingGraphQLType)

@staticmethod
def resolve_things(args, info):
    # returning a query seems to be ok
    return Thing.get_query(info=info)

However the following does not:

class ThingConnection(relay.Connection):
    class Meta:
        node = Thing

things = relay.ConnectionField(ThingConnection)

@staticmethod
def resolve_things(args, info):
    return Thing.get_query(info=info)

graphql.error.located_error.GraphQLLocatedError: object of type 'BaseQuery' has no len()

But this works:

@staticmethod
def resolve_things(args, info):
    return Thing.get_query(info=info).all()

This is all based on try and error. That could be nice to explain that upfront in the doc.

After the previous declaration, I see on my schema that ThingConnection exposes first,last,before and after. This makes me think that pagination is implemented.

However if I try to use the first argument in my query, like things(first:1) {edges{node{name}}}, I get back an error like graphql.error.located_error.GraphQLLocatedError: resolve_farm_connection() got an unexpected keyword argument 'first'

Looks like it's not implemented. So I add the first argument to my resolver signature, without actually implementing the pagination:

@staticmethod
resolve_things(args,info,first=None):
    # 'first' argument is not used anywhere, only added to the signature
    return models.Things.query().all()

There is three Things in my db. If I query things {edges{node{name}}}, I get 3 edges. Then if things(first:1) {edges{node{name}}}, I get only one. So after all even if I don't implement it myself, something in the Connection class will do it. But I still need to allow first in the resolver signature.

I keep exploring this package but it's a slow process of try and error to discover features, find out what is possible and how to do it. The documentation is really lacking in this area.

Agree that it's a huge trial and error effort to understand this lib. My understanding is that pagination is implemented on the edges, you appear to be trying to implement it on the root node. ie I think:
things(first:1) {edges{node{name}}}
should be:
things{edges(first:1){node{name}}}
This keeps it clean when you want to filter things, then paginate the results ie:

things(name:$name,type:$type)
      { edges(first:$limit) {
         node{
           name
         }
       }
    }

That is the benefit that you get from having the tedious amount of boilerplate in your queries.

Ok I'll start completing the doc as I discover about the package: https://github.com/graphql-python/graphene/pull/892

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tricoder42 picture tricoder42  路  4Comments

Glyphack picture Glyphack  路  3Comments

jloveric picture jloveric  路  4Comments

mraak picture mraak  路  3Comments

defrex picture defrex  路  3Comments