GraphQL
Better way to build your API
me@jaro.lt | @chompomonim | +JaroSatkevic
- About GraphQL with full stack in mind
- Short history of GraphQL
- Simple python graphql server
- GraphQL server in real life - tips & tricks
AGENDA
REST is cool, but...
Let's get:
- SW Hero
- His home planet
- His starship
GET /hero/1
GET /hero/1/homeworld
GET /hero/1/starships
GET /hero/1?include=starships,homeworld
OR
OR
GET /hero/1
GET /starships?heroId=1
GET /planets?heroId=1
Over-fetching
Hard to design "proper" api
Documentation hell
How many queries do we need to render this view?
What is GraphQL?
A query language for your API
Short facts:
- Invented at Facebook 5 years ago
- OpenSourced in summer 2015
- Already used at Github, Pinterest, Coursera, Shopify, Intuit, WIX and many more ...
{
hero(id: "1") {
name
birthYear
eyeColor
gender
homeworld {
name
population
}
starships (first: 2) {
name
model
}
}
}
GET /hero/1?include=name,birthYear,gender
GET /hero/1/homeworld
GET /starships?heroId=1&include=name,model
type Person {
name: String!
gender: String
eyeColor: String
birthYear: String
homeplanet: Homeplanet
starships: [Starships]
}
type Starship {
name
model
speed
}
Strictly typed
{
person(personID: "1") {
name
birthYear
eyeColor
gender
homeworld {
name
population
}
starships (first: 1) {
name
model
}
}
}
{
"data": {
person: {
"name": "Luke Skywalker",
"birthYear": "19BBY",
"eyeColor": "blue",
"gender": "male",
"homeworld": {
"name": "Tatooine",
"population": 200000
},
"starships": [
{
"name": "X-wing",
"model": "T-65 X-wing"
}
]
}
}
}
Query
Response
Anyway, why GraphQL?
Features I wanted as UI developer
- Fast data queries with all&only needed data
- Data caching, to avoid refetching
- Allow to work offline
- Specify queries, parses data
- Easy to paginate
- Execute mutations, with cache and pagination
GraphQL clients
Relay
GraphQL on server
A lot of libraries
http://graphql.org/code/
from sanic import Sanic
from sanic.response import json
app = Sanic()
@app.route("/", methods=['POST'])
async def post_root(request):
return json({"hello": "world"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=4000)
from sanic import Sanic
from sanic.response import json
app = Sanic()
#### GraphQL schema
import graphene
class Query(graphene.ObjectType):
labas = graphene.String(description='A typical hello world')
def resolve_labas(self, args, context, info):
return 'Rytas'
schema = graphene.Schema(query=Query)
####
@app.route("/", methods=['POST'])
async def post_root(request):
result = schema.execute(request.json['query'])
return json(result.data)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=4000)
Some tricky places you should think about
How many queries into database?
{
person(personID: "1") {
name
birthYear
eyeColor
gender
homeworld {
name
population
}
starships (first: 10) {
name
model
}
}
}
How big is response for this request?
{
persons {
name
birthYear
eyeColor
gender
homeworld {
name
population
}
starships (first: 10) {
name
model
passangers {
name
gender
homeworld {
name
}
}
}
}
}
Tips & tricks
- Use limits on bigger amount of data (avoid asking for whole DB)
- Define schema first
- Read carefully full specification, it may help
- Prepare for caching your most advanced queries
Questions
Example app: https://github.com/chompomonim/python-graphql-example
me@jaro.lt | @chompomonim | +JaroSatkevic
GraphQL on Python meetup
By Jaro
GraphQL on Python meetup
- 1,187