Python and GraphQL: Building a GraphQL API in Python

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating a GraphQL Schema
  5. Defining GraphQL Types
  6. Resolvers and Queries
  7. Mutations
  8. Testing the GraphQL API
  9. Conclusion

Introduction

In this tutorial, we will learn how to build a GraphQL API using Python. GraphQL is a query language for APIs and a runtime that allows clients to request and fetch the specific data they need, making it efficient and flexible. By the end of this tutorial, you will have a good understanding of how to create a GraphQL API in Python.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of Python. Familiarity with web development concepts and knowledge of REST APIs will also be helpful.

Setup

Before we start building our GraphQL API, let’s set up our development environment.

  1. Make sure you have Python installed on your machine. You can check the installation by running the following command in your terminal:
    python --version
    

    If Python is not installed, download and install it from the official Python website.

  2. Install the necessary Python packages. We will be using graphene, a Python library for building GraphQL APIs, and flask, a lightweight web framework. Run the following command to install these packages:
    pip install graphene flask
    
  3. Create a new directory for your project and navigate into it:
    mkdir graphql-api && cd graphql-api
    
  4. Now, let’s create a new Python file called app.py:
    touch app.py
    

    Open the file in your preferred text editor and let’s start building our GraphQL API!

Creating a GraphQL Schema

Every GraphQL API starts with a schema. A schema defines the types of data that can be queried and the relationships between them. Let’s create a simple schema for a blog API.

  1. Import the necessary packages in app.py:
    from flask import Flask
    from graphene import ObjectType, String, Schema
    
  2. Create a Flask app instance:
    app = Flask(__name__)
    
  3. Define a simple Post object type with fields such as title and content:
    class Post(ObjectType):
        title = String()
        content = String()
    
  4. Create a root query class that will define the available queries in our API. In this case, we’ll have a single query post, which will return a dummy blog post:
    class Query(ObjectType):
        post = String()
    
        def resolve_post(root, info):
            return {
                'title': 'My First Blog Post',
                'content': 'This is my first blog post using GraphQL!',
            }
    
  5. Create a schema instance and bind it to the Flask app in the main section of app.py:
    schema = Schema(query=Query)
    
    if __name__ == '__main__':
        app.run()
    

    Congratulations! You have created a basic GraphQL schema for your blog API.

Defining GraphQL Types

Now that we have a schema, let’s dive deeper into defining GraphQL types. GraphQL comes with built-in scalar types such as String, Int, Float, Boolean, and ID. We can also create custom types to represent more complex data structures.

  1. Import the DateTime scalar type from graphene:
    from graphene import DateTime
    
  2. Add a published_at field of type DateTime to the Post object type:
    class Post(ObjectType):
        title = String()
        content = String()
        published_at = DateTime()
    
  3. Update the resolve_post() method in the Query class to include the published_at field:
    def resolve_post(root, info):
        return {
            'title': 'My First Blog Post',
            'content': 'This is my first blog post using GraphQL!',
            'published_at': datetime.now().isoformat(),
        }
    

    Here, we are using the datetime module to generate the current date and time in ISO format.

  4. Restart the Flask development server by running the app.py script again. You can use the following command:
    python app.py
    

    Now, when you navigate to http://localhost:5000/graphql, you should see a GraphQL playground where you can interact with the API.

Resolvers and Queries

In GraphQL, resolvers are functions responsible for fetching the data requested by the client. Let’s create another resolver to fetch multiple blog posts.

  1. Add a posts field of type list of Post to the Query class:
    class Query(ObjectType):
        post = String()
        posts = List(Post)
    
        def resolve_post(root, info):
            return {
                'title': 'My First Blog Post',
                'content': 'This is my first blog post using GraphQL!',
                'published_at': datetime.now().isoformat(),
            }
    
        def resolve_posts(root, info):
            return [
                {
                    'title': 'Second Blog Post',
                    'content': 'This is my second blog post using GraphQL!',
                    'published_at': datetime.now().isoformat(),
                },
                {
                    'title': 'Third Blog Post',
                    'content': 'This is my third blog post using GraphQL!',
                    'published_at': datetime.now().isoformat(),
                },
            ]
    
  2. Restart the Flask development server and navigate to http://localhost:5000/graphql. You can now query the posts field to fetch multiple blog posts.

    Example query:

    query {
      posts {
        title
        content
        published_at
      }
    }
    

    This will return a list of blog posts with their respective titles, content, and published dates.

Mutations

In addition to queries, GraphQL also supports mutations for modifying data. Let’s add a mutation to create a new blog post.

  1. Define a mutation class with a create_post mutation:
    class CreatePost(Mutation):
        class Arguments:
            title = String(required=True)
            content = String(required=True)
    
        success = Boolean()
        post = Field(Post)
    
        def mutate(root, info, title, content):
            new_post = {
                'title': title,
                'content': content,
                'published_at': datetime.now().isoformat(),
            }
            return CreatePost(success=True, post=new_post)
    

    In this example, the mutation takes two arguments, title and content, both of which are required. The mutation returns a boolean field success and the newly created post.

  2. Add the CreatePost mutation to the Mutation class:
    class Mutation(ObjectType):
        create_post = CreatePost.Field()
    

    Now, we have added the mutation to our schema.

  3. Restart the Flask development server and navigate to http://localhost:5000/graphql. You can now test the createPost mutation to create a new blog post.

    Example mutation:

    mutation {
      createPost(title: "New Post", content: "This is a new blog post") {
        success
        post {
          title
          content
          published_at
        }
      }
    }
    

    This will create a new post with the provided title and content and return the success status along with the created post.

Testing the GraphQL API

To test the API using Python, we can use the requests library to make HTTP requests and interact with the GraphQL API.

  1. Install the requests package by running the following command:
    pip install requests
    
  2. Import the necessary package in app.py:
    import requests
    
  3. Create a test_query() function to send a GraphQL query to the API:
    def test_query(query):
        url = 'http://localhost:5000/graphql'
        response = requests.post(url, json={'query': query})
        return response.json()
    
  4. Call the test_query() function with a sample query as an argument to test the API:
    query = '''
    query {
      posts {
        title
        content
        published_at
      }
    }
    '''
    print(test_query(query))
    

    This will print the response of the query to the console.

Conclusion

Congratulations! You have successfully built a GraphQL API in Python using the graphene and flask libraries. You learned how to create a GraphQL schema, define object types, write resolvers for queries and mutations, and test the API using a GraphQL playground and Python’s requests library. With this knowledge, you can start building powerful and flexible APIs with GraphQL in Python.

Throughout this tutorial, you covered the basics of building a GraphQL API. However, there is much more to explore, such as input types, interfaces, subscriptions, and integrating with databases or other services. Feel free to dive deeper into the official documentation and explore more advanced concepts to enhance your GraphQL API.

Note: It’s important to note that this tutorial serves as a starting point for building GraphQL APIs in Python. The implementation and structure may vary depending on the specific requirements and frameworks you are using.