Loading

Thinking in GraphQL with Python

Mafinar Khan

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

Thinking in GraphQL with Python

Mafinar Khan

Software Developer, Tread Inc

Personal Story

Part I, the Concepts

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.

  • One system queries another for data
  • A strongly typed sub-language that makes it happen
  • Thereby establishing an API between *-ends
  • Server-side environment sits at the surface of the back-end
  • Client-side facilitates powerful data-driven UI capability

Er.. REST?

Let's think about thinking

GraphQL

  • Think about data as a graph
  • And your front-end designer treats it like a database
  • Reads from it, Writes to it
  • URL is like a Database Connection
  • And clients have an SQL like Query

Does it sound like REST?

But they have similar objective(s)

f(data) = UI

What if there is a way to query the data easily no matter how complex?

AND COLOCATE WITH BACKEND?

to expand this...

  • Client sends the query to the server
  • The server parses it
  • Resolves the fields
  • Pulls out data from data-sources
  • Matches with client's demands
    • Or screams at it for error/mismatches
  • Sends out the data
  • Profit!

Think of it as an empty form that clients sends, server fills it up and returns
You send only what you need

Client

Server

Query/Mutation

GraphQL

  • Ask only what you need
  • Know before hand what you'll get
  • OMG Graphiql

DEMO TIME

Part II, Enter Python

Y no Client?

GraphQL Server?

Introducing Graphene

Graphene

  • Awesome API
  • Easy to Reason About
  • Pretty DRY

It all starts with ObjectTypes, and then some Types 

ObjectTypes

  • Source of Data
  • Think Django Model, only Graph theoretically inclined
  • Contains fields, strongly typed fields, just like Django models
  • If you have a field, RESOLVE IT!

Fields

  • Strongly Typed, with Arguments
  • Scalars, Lists and NonNulls
  • Can contains arguments as more types
  • Resolve!
import graphene


class Person(graphene.ObjectType):
    first_name = graphene.String()
    last_name = graphene.String()
    full_name = graphene.String()

    def resolve_full_name(self, info):
        return '{} {}'.format(
            self.first_name, self.last_name)

Mutations

  • Used for Data Changes/Writes
  • Has fields, as in what it will return back
  • Has Arguments, the data it needs to write to
  • That mutate method
import graphene


class CreatePerson(graphene.Mutation):
    class Arguments:
        name = graphene.String()

    ok = graphene.Boolean()
    person = graphene.Field(lambda: Person)

    def mutate(self, info, name):
        person = Person(name=name)
        ok = True
        return CreatePerson(
                person=person, ok=ok)

Schema

Query? Mutation? Type?

schema = schema.Schema(query=RootQueries, mutation=RootMutation)
schema.execute(GRAPHQL_QUERY)

Enter Django!!!

Why Django Graphene?

  • DjangoObjectType knows Django models, DRY!!!
  • Nice view onliner that gives you the whole thing
  • Hate to write mutation? Love DRF? CHECK!
  • Middleware (especially that Debug one!)
  • OMG GraphiQL

work flow

  • The settings.py ritual
  • Add the View
    • GraphQLAPIView
    • Wrap your own
      • Security?
  • Compose queries, mutations as Root
  • Add to Schema
  • Enjoy!
class User(DjangoObjectType):
    class Meta:
        model = UserModel


class Query(graphene.ObjectType):
    users = graphene.List(User)

    def resolve_users(self):
        return UserModel.objects.all()


schema = graphene.Schema(query=Query)

Serializer for Mutation?

from graphene_django.rest_framework.mutation import SerializerMutation


class UserMutation(SerializerMutation):
    class Meta:
        serializer_class = UserSerializer

Filters? Connections?

Got to use Relay!

class AnimalNode(DjangoObjectType):
    class Meta:
        # Assume you have an Animal model defined with the following fields
        model = Animal
        filter_fields = ['name', 'genus', 'is_domesticated']
        interfaces = (relay.Node, )

class Query(ObjectType):
    animal = relay.Node.Field(AnimalNode)
    all_animals = DjangoFilterConnectionField(AnimalNode)
query {
  # Note that fields names become camelcased
  allAnimals(genus: "cat", isDomesticated: true) {
    edges {
      node {
        id,
        name
      }
    }
  }
}

No Relay?

Code!!!

Made with Slides.com