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.
In today's world, more data is consumed and coming up in a massive amount. 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 GraphQLAnchor
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.
Today when you think about APIs, the first thing that might come to your mind is the REST API. In 2000, REST was defined in a Ph.D. dissertation as a resource-oriented architecture with operations like GET, PUT, POST, and DELETE.
REST API architecture is much simpler than RPC and SOAP regarding the data model. REST APIs have been used by countless apps, but it has some shortcomings.
First off, GraphQL is not a REST killer. Like any other successful technology, GraphQL came to solve some problems faced by REST.
Three major issues REST has:
- Overfetching
- Underfetching
- Inflexibility
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.
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.
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 and more productivity among your teams.
Tutorial - Create a Simple GraphQL Wrapper using FlaskAnchor
In this post, you'll build a simple GraphQL wrapper at Hygraph. You'll be able to use Hygraph GraphQL Query API. You'll learn how to authenticate with the Hygraph API using Python, explore the Hygraph GraphQL playground, learn and how to fetch data from GraphQL API and wrap the result in a Flask app.
Create a Hygraph projectAnchor
In this tutorial, you will learn how to use Hygraph to create a pre-configured project like a Todo app. Sign up, and then you'll be redirected to the dashboard of projects. You can create a project from scratch and use a template. If you used the todo app, a new window will pop up like this:
Select the Region that you want to host your content on. If you hit "Create project", you'll have a project.
Set up the project locallyAnchor
Open the terminal and set up a quick virtual environment like the following:
python3 -m venv venv;. venv/bin/activate;pip install --upgrade pip
Now, you're ready to install dependencies for your project with pip:
pip install flask requests
You've installed Flask, a microframework that you'll use for the simple web app to wrap data sent from GraphQL API.
You'll also need requests for authentication and to be able to fetch data from the Hygraph GraphQL API.
Set up the Flask appAnchor
To configure the flask app location, set up an environment variable with the name of your application (say, api.py
file):
export FLASK_APP=api.py
In this api.py file, create the simple Flask setup like the following:
from flask import Flaskapp = Flask(__name__)@app.route("/get_todo")def get_todo():return {"todo text": "data from the API"}
Type flask run
in the terminal and open the browser on localhost:5000/get_todo endpoint. A simple JSON with the "todo text" key is returned.
Hygraph authenticationAnchor
To authenticate your todo app on Hygraph, you need to know the endpoint that you want to access, the GraphQL query you want to send to the request, and the token generated by Hygraph.
To get the endpoint of your Hygraph application, navigate to the Project settings tab on the left and select Endpoints inside API Access page. Copy the endpoint under Content API and paste it somewhere.
If you scroll down on the same API Access page, you'll see a token generated by Hygraph called HYGRAPH_TOKEN. Under Value column, click on the token to copy it. Paste it somewhere, you'll need it.
What's left is the GraphQL query that you want to pass to the request. Navigate to the API playground on which you can experiment with GraphQL queries. Write this query on the playground:
query MyQuery {todo(where: {id: "ckz8d4mlc0qjq0b13gcgbieni"}) {descriptioncompleted}}
A quick write-up for the previous query is to select the todo dropdown and the id under the where clause and then the fields you want to query. In this case, it's description
and completed
.
If you want to get the id related to your project, navigate to the Content tab. You'll find each column representing a specific field in the schema and each row representing a specific entry in your application.
Now, you're ready to authenticate your app. Open the api.py
and your project is now like the following:
import requestsimport jsonimport osfrom flask import Flaskquery_todo = """query MyQuery {todo(where: {id: "ckz8d4mlc0qjq0b13gcgbieni"}) {descriptioncompleted}}"""url = "https://api-<region>.hygraph.com/v2/<some hash>/master" # paste your Content API endpointtoken = os.getenv("HYGRAPH_TOKEN")headers = {"Authorization": f"Bearer {token}"}app = Flask(__name__)@app.route("/get_todo")def get_todo():payload = {"query": query_todo}r = requests.post(url, json=payload, headers=headers)json_data = r.json()return {"todo text": json_data["data"]["todo"]["description"]}
Notes:
- The url is the token
- The payload is a dictionary that contains the query pointing to the query_todo which is the string of the query you wrote at the Hygraph API playground
- The headers contain the Authorization key which contains the string "Bearer " + ""
- The r object contains the response of the post request that you sent to the Hygraph API
- The json_data is a JSON conversion from the r Python object
Finally, the response coming from the query (see the picture above about the playground):
{"data": {"todo": {"description": "Hello","completed": null}}}
So if you want to get the description of that JSON, you need to traverse through that JSON. The get_todo endpoint returns a "todo text" key with the value of the description as indicated.
Query the todo itemAnchor
Now, you're ready to move on and run the Flask app. Before that, you need to set up the environment variable of the Hygraph token with the following command:
export HYGRAPH_TOKEN=<your Hygraph token>
Run the Flask app with flask run and open the local host on get_todo endpoint. You'll see a response with the following:
{"todo text": "Hello"}
MutationAnchor
If you want to modify data or create new one, use the mutation root type in GraphQL. Explore that in the Hygraph API playground and write the following:
mutation editTodo {updateTodo(data: {description: "write a blog post",completed: true},where: {id: "ckz8d4mlc0qjq0b13gcgbieni"}) {iddescriptioncompleted}}
This mutation updates the previous query you fetched with a new description and a completed boolean value instead of null. Then, it will return the id, description, and completed fields with the updated values.
When you hit Run, you'll find two values to choose from. Select the editTodo mutation name. Now, if you run the Flask app again, you'll find a response with the new description that you fetched:
{"todo text": "write a blog post"}
ConclusionAnchor
This tutorial shows you how to use GraphQL with Python to fetch data. You've explored a GraphQL API and how to use its playground to write queries and mutations. You now have the ability to authenticate your app using Python with requests. And you've linked a Flask app with GraphQL API and fetched information from it.