GraphQL Overview¶
apischema supports GraphQL through the graphql-core library.
You can install this dependency directly with apischema using the following extra requirement:
GraphQL supports consists of generating a GraphQL schema graphql.GraphQLSchema
from your data model and endpoints (queries/mutations/subscribtions), in a similar way than the JSON schema generation. This schema can then be used through graphql-core library to query/mutate/subscribe.
from dataclasses import dataclass
from datetime import date, datetime
from typing import Collection
from uuid import UUID, uuid4
from graphql import graphql_sync, print_schema
from apischema.graphql import graphql_schema, resolver
@dataclass
class User:
id: UUID
username: str
birthday: date | None = None
@resolver
def posts(self) -> Collection["Post"]:
return [post for post in POSTS if post.author.id == self.id]
@dataclass
class Post:
id: UUID
author: User
date: datetime
content: str
USERS = [User(uuid4(), "foo"), User(uuid4(), "bar")]
POSTS = [Post(uuid4(), USERS[0], datetime.now(), "Hello world!")]
def users() -> Collection[User]:
return USERS
def posts() -> Collection[Post]:
return POSTS
def user(username: str) -> User | None:
for user in users():
if user.username == username:
return user
else:
return None
schema = graphql_schema(query=[users, user, posts], id_types={UUID})
schema_str = """\
type Query {
users: [User!]!
user(username: String!): User
posts: [Post!]!
}
type User {
id: ID!
username: String!
birthday: Date
posts: [Post!]!
}
scalar Date
type Post {
id: ID!
author: User!
date: Datetime!
content: String!
}
scalar Datetime
"""
assert print_schema(schema) == schema_str
query = """
{
users {
username
posts {
content
}
}
}
"""
assert graphql_sync(schema, query).data == {
"users": [
{"username": "foo", "posts": [{"content": "Hello world!"}]},
{"username": "bar", "posts": []},
]
}
GraphQL is fully integrated with the rest of apischema features, especially conversions, so it's easy to integrate ORM and other custom types in the generated schema; this concerns query results but also arguments.
By the way, while GraphQL doesn't support constraints, apischema still offers you all the power of its validation feature. In fact, apischema deserialize and validate all the arguments passed to resolvers.
FAQ¶
Is it possible to use the same classes to do both GraphQL and REST-API?¶
Yes it is. GraphQL has some restrictions in comparison to JSON schema (see next section), but this taken in account, all of your code can be reused. In fact, GraphQL endpoints can also be used both by a GraphQL API and a more traditional REST or RPC API.