3 Relay Pagination example
Baptiste Darthenay edited this page 2020-07-31 11:14:24 +02:00

For this example, we're using DjangoObjectType and a django model for Place. Neither of these is necessary, and it's being included only to present a complete (almost) example. Simply replace the model assignment, and use the appropriate ObjectType in place of DjangoObjectType in the initial type declaration (class PlaceNodeType(DjangoObjectType) herein) for your application, and pagination will be yours!

For this example, we're going to assume a basic understanding of how Relay pagination works, and just quickly provide you with the basics of graphene relay pagination's how.

In a nutshell, pagination is implemented via graphene relay's Connection and ConnectionField pairing. With these in place, you'll see pageInfo available within your queries. It looks something like this:

"pageInfo": {
    "startCursor": "YXJyYXljb25uZWN0aW9uOjQx",
    "endCursor": "YXJyYXljb25uZWN0aW9uOjQz",
    "hasNextPage": false,
    "hasPreviousPage": true
},

In addition to a cursor element within edges that will show you the cursor id for each element, like so:

edges {
  cursor
  node {
    <whatever>
  }
}

The basic schema below provides relay cursor-based pagination, combined with graphene_django filter capability.

from graphene import relay
from graphene_django.types import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField

from <wherever your models exist> import Place

class PlaceNodeType(DjangoObjectType):
    class Meta:
        model = Place
        interfaces = (relay.Node, )
        filter_fields = {"name": ["exact", "icontains", "istartswith"]}


class Query(object):
    places = DjangoFilterConnectionField(PlaceNodeType)

The following query, (the pageInfo element is included for illustration, but isn't necessary for the query to resolve):

{
  places(first: 3, after: "YXJyYXljb25uZWN0aW9uOjQx") {
    pageInfo {
      startCursor
      endCursor
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        id
        name
      }
    }
  }
}

Gives us:

{
  "data": {
    "places": {
      "pageInfo": {
        "startCursor": "YXJyYXljb25uZWN0aW9uOjQy",
        "endCursor": "YXJyYXljb25uZWN0aW9uOjQ0",
        "hasNextPage": true,
        "hasPreviousPage": false
      },
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjQy",
          "node": {
            "id": "UGxhY2VfTm9kZV9UeXBlOjQz",
            "name": "Wilton, Franklin, Maine, United States"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjQz",
          "node": {
            "id": "UGxhY2VfTm9kZV9UeXBlOjQ0",
            "name": "Boise City, Ada, Idaho, United States"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjQ0",
          "node": {
            "id": "UGxhY2VfTm9kZV9UeXBlOjQ1",
            "name": "Helena, Shelby, Akabama, USA"
          }
        }
      ]
    }
  }
}