Easily restore your project to a previous version with our new Instant One-click Backup Recovery

How to Use GraphQL with Python

Let's take a look at how you can query GraphQL endpoints with Python and build a demo To Do List app in Flask.
EzzEddin Abdullah

EzzEddin Abdullah

Nov 01, 2022
How to Use GraphQL with Python

Increasing amounts of data are being consumed and generated today. Clients, on one side, need to load data as fast as they can. Developers, on the other side, need to make their apps performant. If your app is fast, your clients will have a better user experience and will be happy, and eventually, your business will make more money.

Modern apps should be faster than the old ones. Your app should get data fast from the server to the client. GraphQL is a sure solution for that.

#Why use GraphQL

Back in 2012, Facebook engineers found that iOS and Android apps frequently crashed. They decided to look at how to improve how Facebook data was being sent to the client apps. Then they built GraphQL for their internal use. In September 2015, Facebook released GraphQL to the public.

In 2000, a Ph.D. dissertation defined REST as a resource-oriented architecture with operations like GET, PUT, POST, and DELETE. Regarding the data model, REST API architecture is much simpler than RPC and SOAP. Countless apps have used REST APIs, however, they have shortcomings, making GraphQL a superior option.

Three major issues REST has:

  • Over fetching

    In the REST world, you get too much data in the response you don't need. This problem is called overfetching. In GraphQL, you're fetching only the fields you want. This makes GraphQL more declarative and faster.

  • Under fetching

    In REST, if you developed an endpoint that returns specific data and there is a feature request to fetch more data from the response, you would need additional requests to get these new data. This is how you underfetched. In GraphQL, you must add new key(s) to the nested query. This will request the data all in just one fetch.

  • Inflexibility

    Another pain of REST APIs is the inflexibility, especially if your app is getting bigger. In REST, when a client needs a change in your app, you will probably create a new endpoint. These endpoints keep adding up whenever there is a need. Thus, more collaboration between your backend and frontend teams. This will cost time and speed, as new endpoints mean more HTTP requests from the clients. In GraphQL, a single endpoint is typically involved. This makes easy organization of data easy and more productivity among your teams.

#Building a simple GraphQL wrapper using Flask

In this post, we will build a simple GraphQL wrapper on top of Hygraph. You'll be able to use the Hygraph GraphQL Query API. We will learn how to authenticate with the Hygraph API using Python, fetch data from the Hygraph server, and wrap the result in a Flask app.

Creating a Hygraph project

Sign up on Hygraph, and please follow this quickstart guide, to create a project, set up a data model, and publish some content to it.

Setting up the Python Flask app

Let us open the terminal and set up a quick virtual environment using the commands below

python -m venv venv
# Linux
source venv/bin/activate
# Windows
venv\Scripts\activate
pip install --upgrade pip

We will see three ways to make GraphQL requests with Python:

Let us install dependencies, all required dependencies for our project with pip:

pip install flask requests gql graphqlclient

Create a directory structure as shown below

flask_app/
├── app/
│ ├── __init__.py
│ ├── routes.py
│ └── services.py
├── run.py
├── requirements.txt
└── venv/

Add the following code to the respective files

run.py

from app import create_app
app = create_app()
if __name__ == '__main__':
app.run()

app/__init__.py

from flask import Flask
def create_app():
app = Flask(__name__)
# Import routes
from .routes import main_routes
app.register_blueprint(main_routes)
return app

app/routes.py

from flask import Blueprint, jsonify
from .services import fetch_data_with_requests, fetch_data_with_gql
main_routes = Blueprint('main', __name__)
@main_routes.route('/get_data_1', methods=['GET'])
def get_data_1():
data = fetch_data_with_requests()
return jsonify(data)
@main_routes.route('/get_data_2', methods=['GET'])
def get_data_2():
data = fetch_data_with_gql()
return jsonify(data)
@main_routes.route('/get_data_3', methods=['GET'])
def get_data_3():
data = fetch_data_with_graphqlclient()
return jsonify(data)

So far, we have created a very basic Flask application and defined three routes: get_data_1 and get_data_2, and get_data_3.These three routes will use the service file to get data from our Hygraph API using different packages and return it to the client. The get_data_1 route is supposed to use the requests package, while the get_data_2 will use a more structured gql package to make GraphQL requests, and the get_data_3 route will use the graphqlclient to make GraphQL requests.

Making GraphQL requests from Python

Let us create our service file and import some fundamental requirements there.

app/services.py

import requests
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
from graphqlclient import GraphQLClient
import json
URL = "add_your_hygraph_url_here"
TOKEN = "add_your_hygraph_token_here"
QUERY = '''
query getUsers {
products {
name
price
image {
url
fileName
}
}
}
'''

We have imported the packages that we will require, defined the GraphQL query that we need to make on the GraphQL server, and declared two variables around our hygraph URL and TOKEN, do replace them with your own Hygraph URL and TOKEN.

Requests

Let us make a GraphQL query using the requests package. requests is a general package that can be used to make any HTTP/S requests. For this use case, we need to define headers by providing an authentication bearer token and send a POST request to the Hygraph server with the query and headers.

import requests
def fetch_data_with_requests():
headers = {"Authorization": f"Bearer {TOKEN}"}
response = requests.post(URL, json={'query': QUERY}, headers=headers)
return response.json()

GraphQL

On the other hand, gql is more of a GraphQL-specific client package and is one of the top GraphQL Client libraries available for Python. We need to set up a transport and a client variable as shown below.

transport = AIOHTTPTransport(url=URL, headers={"Authorization": f"Bearer {TOKEN}"})
client = Client(transport=transport, fetch_schema_from_transport=True)

Then we can wrap our GraphQL operation using the gql tag and execute the query.

query = gql(QUERY)
result = client.execute(query)

The final code for making a GraphQL request with gql will look like this

from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
def fetch_data_with_gql():
transport = AIOHTTPTransport(url=URL, headers={"Authorization": f"Bearer {TOKEN}"})
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(QUERY)
result = client.execute(query)
return result

Also, in a proper production app, we only need to define the transport and client once when a class initializes, later we can use the same class instance and execute GraphQL operations from anywhere in our application without worrying about connection details.

GraphQLClient

For graphqlclient, we need to create a client using the GraphQLClient provided by the library, we can add the Hygraph token using the inject_token function on the client and pass it the token, finally, we will need to convert the string response to parsable JSON using json.loads and that’s it.

from graphqlclient import GraphQLClient
import json
def fetch_data_with_graphqlclient():
client = GraphQLClient(URL)
client.inject_token(TOKEN)
result = json.loads(client.execute(QUERY))
return result

Below is the final service file

app/services.py

import requests
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
from graphqlclient import GraphQLClient
import json
URL = "add_your_hygraph_url_here"
TOKEN = "add_your_hygraph_token_here"
QUERY = '''
query getUsers {
products {
name
price
image {
url
fileName
}
}
}
def fetch_data_with_requests():
headers = {"Authorization": f"Bearer {TOKEN}"}
response = requests.post(URL, json={'query': QUERY}, headers=headers)
return response.json()
def fetch_data_with_gql():
transport = AIOHTTPTransport(url=URL, headers={"Authorization": f"Bearer {TOKEN}"})
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(QUERY)
result = client.execute(query)
return result
def fetch_data_with_graphqlclient():
client = GraphQLClient(URL)
client.inject_token(TOKEN)
result = json.loads(client.execute(QUERY))
return result

#Conclusion

In this article, we went through the problems that GraphQL solves over REST. Through the quickstart, we created data models and published some content in Hygraph and finally, we built a flask wrapper app in Python to query our content via three libraries - requests, gql,andgraphqlclient.

Blog Author

EzzEddin Abdullah

EzzEddin Abdullah