Skip to content

Latest commit

 

History

History
222 lines (158 loc) · 4.86 KB

File metadata and controls

222 lines (158 loc) · 4.86 KB

GraphQL: Experimentation and Django back end

This is analogous to what we did with REST, but we'll be doing it with GraphQL instead.

Resources

Experimentation with the graphiql Interface

Click here to get to the demo page.

Enter some queries in the left panel.

Show all the links to the nodes on the graph:

{
  allStarships
}

Or we could get all the starships themselves:

{
  allStarships {
    starships
  }
}

Or get the name and ID:

{
  allStarships {
    starships {
      id
      name
    }
  }
}

Mess around with this. With GraphQL you just specify the keys you want.

Click the Docs tab in the upper right. Explore the metadata and see what you can look up.

Installing the graphene GraphQL Library for Django

Get into the shell.

pipenv shell

We're going to install Django's GraphQL lib, graphene_django.

pipenv install graphene_django

What next? Add to INSTALLED_APPS.

djorg/settings.py:

    'graphene_django',

Define a GraphQL Schema

Next, we need to define the schema that describes the data.

New file notes/schema.py:

from graphene_django import DjangoObjectType
import graphene
from .models import PersonalNote  # Trouble brewing!

class PersonalNote(DjangoObjectType):
    pass  # TODO

We have to do something weird here. To have GraphQL expose our PersonalNotes as PersonalNotes, we have to call the schema class PersonalNote. But we already have a class PersonalNote in the model. This is a name collision.

We'll work around this by aliasing our PersonalNote from .models using the as keyword.

from graphene_django import DjangoObjectType
import graphene
from .models import PersonalNote as PersonalNoteModel  # <-- Right here

class PersonalNote(DjangoObjectType):
    """Describe which model we want to expose through GraphQL."""
    class Meta:
        model = PersonalNoteModel

        # Describe the data as a node in a graph for GraphQL
        interface = (graphene.relay.Node, )

class Query(graphene.ObjectType):
    """Describe which records we want to show."""
    notes = graphene.List(Note)

    def resolve_notes(self, info):
        """Decide what notes to return."""
        pass # TODO

Note the analogies between this and what we did to set up REST in notes/api.py.

Now let's finish resolve_notes() in Query:

from django.conf import settings
from graphene_django import DjangoObjectType
import graphene
from .models import PersonalNote as PersonalNoteModel

class PersonalNote(DjangoObjectType):
    """Describe which model we want to expose through GraphQL."""
    class Meta:
        model = PersonalNoteModel

        # Describing the data as a node in a graph for GraphQL
        interfaces = (graphene.relay.Node, )

class Query(graphene.ObjectType):
    """Describe which records we want to show."""
    personalnotes = graphene.List(PersonalNote)

    def resolve_personalnotes(self, info):
        """Decide what notes to return."""
        user = info.context.user  # Find this with the debugger

        if user.is_anonymous:
            return PersonalNoteModel.objects.none()
        else:
            return PersonalNoteModel.objects.filter(user=user)

# Add a schema and attach to the query
schema = graphene.Schema(query=Query)

Lastly, at the very bottom, we had to tell graphene that schema query behavior is based on the Query class we just defined.

Configure graphene and set the URL endpoint

Now what do we have to do to get it going?

So far we've

  • Installed graphene
  • Wrote this schema describing the data

Let's configure in djorg/settings.py:

GRAPHENE = {
    'SCHEMA': 'notes.schema.schema'  # dir.file.varname
}

Need to make an endpoint URL. Just a single one for all the queries.

django/urls.py:

from graphene_django.views import GraphQLView
    # in urlpatterns:
    path('graphql/', GraphQLView.as_view(graphiql=True)),

graphiql ("graphy-QL") is the UI we were experimenting with initially. It comes built-in with graphene!

Don't have to specify the schema here since we did that in the settings.

./manage.py runserver to see if it works.

Hit the /graphql/ endpoint to see the graphiql interface.

Check out the Docs tab and see all the information about our Notes. Try a query:

{
  personalnotes
}

More complex:

{
  personalnotes {
    title
    content
    lastModified
  }
}

There we go!

You can do things at this point to set up more advanced filters, not include fields in the output, etc.

You can decide to write a front end to either REST or GraphQL.