graphql-dsl¶
Quick intro¶
Let’s take a manually written GraphQL query:
query {
hero {
name
}
droid(id: "2000") {
name
}
}
With graphql-dsl
you can construct a similar query with the following Python snippet:
from typing import NamedTuple
from graphql_dsl import *
class Hero(NamedTuple):
name: str
class Droid(NamedTuple):
name: str
class HeroAndDroid(NamedTuple):
hero: Hero
droid: Droid
class Input(NamedTuple):
droid_id: ID
q = GQL( QUERY | HeroAndDroid
| WITH | Input
| PASS | Input.droid_id * TO * HeroAndDroid.droid * AS * 'id'
)
print(q.query)
and the output will be:
query HeroAndDroid($droidId:ID!){hero{name}droid(id:$droidId){name}}
The query builder supports both NamedTuple
and @dataclass
types, yet the latter has a slightly different
field reference syntax (because dataclasses don’t define class-level field getters):
from dataclasses import dataclass
from graphql_dsl import *
@dataclass
class Hero:
name: str
@dataclass
class Droid:
name: str
@dataclass
class HeroAndDroid:
hero: Hero
droid: Droid
@dataclass
class Input:
droid_id: ID
q = GQL( QUERY | HeroAndDroid
| WITH | Input
| PASS | (Input, 'droid_id') * TO * (HeroAndDroid, 'droid') * AS * 'id'
)
Simple queries¶
Let’s use Countries API and prepare the simplest query for it.
We want to fetch a list of all country codes
from typing import Sequence, NamedTuple
class Country(NamedTuple):
code: str
class Query(NamedTuple):
countries: Sequence[Country]
We can start composing our query with:
from graphql_dsl import QUERY
countries_query = QUERY | Query
If we don’t need to provide input parameters to the query, we can immediately compile it:
from graphql_dsl import GQL
compiled_query = GQL(countries_query)
Now we are able to call the service and receive the typed result from it:
import requests
response = requests.post(
url="https://countries.trevorblades.com/",
json={
"operationName": compiled_query.name,
"query": compiled_query.query,
}
)
data = compiled_query.get_result(response.json())
assert isinstance(data, Query)
# will print AD, AE, AF, AG, AI, AL, AM, AO, ...
print(', '.join(country.code for country in data.countries))