Using the Schema Definition Language
Above we defined the GraphQL schema as Python code, using the GraphQLSchema
class and other classes representing the various GraphQL types.
GraphQL-core 3 also provides a language-agnostic way of defining a GraphQL schema
using the GraphQL schema definition language (SDL) which is also part of the GraphQL
specification. To do this, we simply feed the SDL as a string to the
build_schema()
function in graphql.utilities
:
from graphql import build_schema
schema = build_schema("""
enum Episode { NEWHOPE, EMPIRE, JEDI }
interface Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
type Query {
hero(episode: Episode): Character
human(id: String!): Human
droid(id: String!): Droid
}
""")
The result is a GraphQLSchema
object just like the one we defined above, except
for the resolver functions which cannot be defined in the SDL.
We would need to manually attach these functions to the schema, like so:
schema.query_type.fields['hero'].resolve = get_hero
schema.get_type('Character').resolve_type = get_character_type
Another problem is that the SDL does not define the server side values of the
Episode
enum type which are returned by the resolver functions and which are
different from the names used for the episode.
So we would also need to manually define these values, like so:
for name, value in schema.get_type('Episode').values.items():
value.value = EpisodeEnum[name].value
This would allow us to query the schema built from SDL just like the manually assembled schema:
from graphql import graphql_sync
result = graphql_sync(schema, """
{
hero(episode: EMPIRE) {
name
appearsIn
}
}
""")
print(result)
And we would get the expected result:
ExecutionResult(
data={'hero': {'name': 'Luke Skywalker',
'appearsIn': ['NEWHOPE', 'EMPIRE', 'JEDI']}},
errors=None)