Unlock the Power of GraphQL with Ariadne

Introducing GraphQL

As a frontend developer and long-time Jamstack enthusiast, I’ve had my fair share of frustrations with traditional REST APIs. But then I discovered GraphQL, and it was a game-changer. The idea is simple yet revolutionary: the API itself defines what kind of data it can understand and exposes a single endpoint to the user. The user provides a query to that endpoint, and the API returns a JSON response with the requested data.

What is Ariadne?

Ariadne is a Python library that helps you create a GraphQL API without the extra baggage. As a Python enthusiast, I was excited to dive into Ariadne and explore its capabilities.

Getting Started with Ariadne

To get started with Ariadne, you’ll need to have Python set up on your computer and install Ariadne using pip3:

pip3 install ariadne

How Ariadne Works

Ariadne uses GraphQL’s special schema definition language to define types. You can think of it as a TypeScript interface, where you define the keys of an object and the types of the values of each key. Every app in Ariadne needs a type called Query, which will be compared against the input of the program.

Building a Sample GraphQL API

Let’s build a sample GraphQL API that takes the slugged name of a favorite sitcom as a parameter and returns a Sitcom type with fields for the name, number of seasons, and characters. We’ll use a simple Python dictionary structure to store our data.

Defining Our Types

We’ll define our types using Ariadne’s schema definition language:

type Sitcom {
    name: String!
    seasons: Int!
    characters: [Character!]!
}

type Character {
    firstName: String!
    lastName: String!
    actorName: String!
}

Resolvers: The Magic Happens

Ariadne’s main purpose is to scan over the input query and run a resolver function to get the value of each key. We’ll create resolver functions for our hello key and our Sitcom type:

def resolve_hello(obj, info):
    return "Hello, World!"

def resolve_sitcom(obj, info, slug):
    sitcoms = {
        "friends": {"name": "Friends", "seasons": 10, "characters": [...]},
        "how-i-met-your-mother": {"name": "How I Met Your Mother", "seasons": 9, "characters": [...]},
        #...
    }
    return sitcoms.get(slug)

Putting it All Together

We’ll put our types and resolvers together to create a fully functional GraphQL API. We’ll use Uvicorn to serve our API and test it out:

from ariadne import graphql_sync, make_executable_schema, load_schema_from_path
from ariadne.constants import PLAYGROUND_HTML
from starlette.app import App
from starlette.requests import Request
from starlette.responses import HTMLResponse
from starlette.routing import Mount
from uvicorn import run

type_defs = load_schema_from_path("schema.graphql")
query = """
    type Query {
        hello: String!
        sitcom(slug: String!): Sitcom
    }
"""

schema = make_executable_schema(type_defs, query, resolve_hello, resolve_sitcom)

app = App(routes=[
    Mount("/graphql", App(routes=[
        Mount("/{path:path}", graphql_sync, schema=schema),
        Mount("/", lambda request: HTMLResponse(content=PLAYGROUND_HTML, status_code=200)),
    ])),
])

run(app, host="0.0.0.0", port=8000)

Additional Benefits of Using Ariadne

There are many benefits to using Ariadne, including:

  • The ability to use a more rugged data source like a proper database
  • The ability to create mutations to update existing records or add new ones
  • The ability to create a GraphQL service around more useful data, such as an existing REST API

With its simple yet powerful schema definition language and resolver functions, Ariadne makes it easy to create a robust and scalable API. So why not give it a try and see what you can build?

Leave a Reply