Python Flask GraphQL with Graphene
GraphQL is a query language for APIs. It's becoming more popular because of the many benefits it offers compared to REST APIs, of which the most important one is smarter data fetching.
The querying model offered by GraphQL is showing its real power when it comes to working with large APIs. It's basically API specification or protocol which provides more efficient, powerful and
alternative to REST. It developed by open-source Facebook and now it's maintained by a large community of companies and individuals from all over the world.
As nowadays declarative programming is becoming popular day by day. It's sound good cause GraphQL also enables declarative data fetching. Instead of multiple rest API calling increases
roundtrips, GraphQL server only exposes a single endpoint and responds with precisely the data a client asked for. we will look it with example.
GraphQL vs REST
- GraphQL allows us to specify what data we need in a query and that's what's going to be included in a response – nothing more, nothing less, just the data we asked for in a single request. On the other hand, when fetching for the same data with REST we would end up with multiple REST roundtrips ...
Let's deep drive into GraphQL vs REST with an example:
To illustrate the major differences between REST and GraphQL when it comes to fetching data from an API,
- let’s consider a simple example scenario: In a blogging application, an app needs to display the titles of the posts of a specific user.
- The same screen also displays the names of the last 3 followers of that user. How would that situation be solved with REST and GraphQL?
Python Flask GraphQL with Graphene
GraphQL is a query language for APIs. It's becoming more popular because of the many benefits it offers compared to REST APIs, of which the most important one is smarter data fetching.
The querying model offered by GraphQL is showing its real power when it comes to working with large APIs. It's basically API specification or protocol which provides more efficient, powerful and
alternative to REST. It developed by open-source Facebook and now it's maintained by a large community of companies and individuals from all over the world.
As nowadays declarative programming is becoming popular day by day. It's sound good cause GraphQL also enables declarative data fetching. Instead of multiple rest API calling increases
roundtrips, GraphQL server only exposes a single endpoint and responds with precisely the data a client asked for. we will look it with example.
GraphQL vs REST
- GraphQL allows us to specify what data we need in a query and that's what's going to be included in a response – nothing more, nothing less, just the data we asked for in a single request. On the other hand, when fetching for the same data with REST we would end up with multiple REST roundtrips ...
Let's deep drive into GraphQL vs REST with an example:
To illustrate the major differences between REST and GraphQL when it comes to fetching data from an API,
- let’s consider a simple example scenario: In a blogging application, an app needs to display the titles of the posts of a specific user.
- The same screen also displays the names of the last 3 followers of that user. How would that situation be solved with REST and GraphQL?
Solution with a REST API:
In REST we fetch data through multiple endpoints.
- In the example, these could be
/users/<id>
endpoint to fetch the initialuser data
. - Secondly, there’s likely to be a
/users/<id>/posts
endpoint that returnsall the posts for a user
. - Finally, The third endpoint will then be the
/users/<id>/followers
that returns alist of followers per user
.
Note: Using REST, we have to make different three requests to fetch data, We're also overfetching additional information that's not needed.
On the other hand, we can create single REST endpoint which serves our desire data like /users/posts/followers/<id>
that save networking roundtrips, It's okay
But it will be horrible. when we try to change additional filters attributes ex. date
or more /users/posts/followers/<id>/<date>
.
See our API URLs are increasing, which is hard for maintains and tracks.
Solution with GraphQL API:
In GraphQL simply send a single query to the GraphQL server. The server then responds with a JSON data
Note: Using GraphQL, the client can specify exactly the data it needs in a query. Notice that the structure of the server’s response follows precisely the nested structure defined in the query.
Isn't it cool staff ?. It's enough about theory. Let's implement GraphQL server using Python Graphene
Implement GraphQL server using Python Graphene
Graphene is basically python GraphQl client library. with the help of that, we can create your GraphQL Server.
Setting up your project
🔰 First, to set up a project create a directory/folder like below
$ mkdir graphql-flask
$ cd graphql-flask
🔰 It's time to create a virtual environment. So we can avoid conflict, from global packages.
It helps us to manage different packages versions for individual projects. if you don't have a virtual environment then
install it using below command,
$ pip install virtualenv
$ virtualenv venv
$ source venv/bin/activate
Install require dependencies, using below command:
$ pip install flask flask-graphql flask-migrate flask-sqlalchemy graphene graphene-sqlalchemy
🔰 Now, we need to initialize our database to do so, We need to create another python script to process easier,
create seed.py
file and includes,
from app import db, User, Post
db.create_all() # create tables from models
user1 = User(
name="Sadhan Sarker",
email='cse.sadhan@gmail.com'
)
post1 = Post()
post1.title = "Blog Post Title 1"
post1.body = "This is the first blog post 1"
post1.author = user1
db.session.add(post1)
db.session.add(user1)
db.session.commit()
print(User.query.all())
print(Post.query.all())
We need to run that script from a virtual environment using,
python seed.py
👏 Great! Well, we are doing lots. we are almost closer to end,
🔰 Eventually, create 'app.py' and includes,
import os
import graphene
from flask import Flask
from flask_graphql import GraphQLView
from flask_sqlalchemy import SQLAlchemy
from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
# Database Configs [Check it base on other Database Configuration]
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'database.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# Initialize Database
db = SQLAlchemy(app)
# ------------------ Database Models ------------------
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256))
email = db.Column(db.String(256), index=True, unique=True) # index => should not be duplicate
posts = db.relationship('Post', backref='author')
def __repr__(self):
return '<User %r>' % self.email
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(256))
body = db.Column(db.Text)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
def __repr__(self):
return '<Post %r>' % self.title
# ------------------ Graphql Schemas ------------------
# Objects Schema
class PostObject(SQLAlchemyObjectType):
class Meta:
model = Post
interfaces = (graphene.relay.Node,)
class UserObject(SQLAlchemyObjectType):
class Meta:
model = User
interfaces = (graphene.relay.Node,)
class Query(graphene.ObjectType):
node = graphene.relay.Node.Field()
all_posts = SQLAlchemyConnectionField(PostObject)
all_users = SQLAlchemyConnectionField(UserObject)
# noinspection PyTypeChecker
schema_query = graphene.Schema(query=Query)
# Mutation Objects Schema
class CreatePost(graphene.Mutation):
class Arguments:
title = graphene.String(required=True)
body = graphene.String(required=True)
email = graphene.String(required=True)
post = graphene.Field(lambda: PostObject)
def mutate(self, info, title, body, email):
user = User.query.filter_by(email=email).first()
post = Post(title=title, body=body)
if user is not None:
post.author = user
db.session.add(post)
db.session.commit()
return CreatePost(post=post)
class Mutation(graphene.ObjectType):
save_post = CreatePost.Field()
# noinspection PyTypeChecker
schema_mutation = graphene.Schema(query=Query, mutation=Mutation)
# Flask Rest & Graphql Routes
@app.route('/')
def hello_world():
return 'Hello From Graphql Tutorial!'
# /graphql-query
app.add_url_rule('/graphql-query', view_func=GraphQLView.as_view(
'graphql-query',
schema=schema_query, graphiql=True
))
# /graphql-mutation
app.add_url_rule('/graphql-mutation', view_func=GraphQLView.as_view(
'graphql-mutation',
schema=schema_mutation, graphiql=True
))
if __name__ == '__main__':
app.run()
✅We made it together, successfully we are able to integrate graphql with graphene. Now' run and test our app.
To Run Application,
$ python app.py
Test GraphQL API'S by following steps
Use any Rest Client like PostMan or cRUL we can use other clients also,
## 1. Rest API examples
GET http://127.0.0.1:5000/
### Graphql query-api example
POST http://127.0.0.1:5000/graphql-query
Content-Type: application/graphql
{
allPosts{
edges{
node{
title
author{
email
}
}
}
}
}
### 2. Graphql mutation-api example
POST http://127.0.0.1:5000/graphql-mutation
Content-Type: application/graphql
mutation {
savePost(email:"cse.sadhan@gmail.com", title:"Title 2", body:"Blog post 2") {
post{
title
body
author{
email
}
}
}
}
###
```
👌 Congratulations!. & Thank You!
Feel free to comments, If you have any issues & queries.
#### References:
- https://www.howtographql.com
- https://graphql.org/
- https://docs.graphene-python.org/projects/sqlalchemy/en/latest/tutorial/
Top comments (4)
"On the other hand, when fetching for the same data with REST we would end up with multiple REST roundtrips"
IMO, anything graphql does, rest can and vice versa. But when you're doing more REST things on a graphql api, then you should just go REST.
Many rest frameworks support "data" or property filtering.
Said every REST developer who is too afraid to jump into the GraphQl world :P
Great Article! GraphQL looks a lot more easier than making a Restful API in flask. I'm currently studying how to build one using Flask and kind end up loving how easy you can build things using Python and Flaks.
There is a duplicated paragraph on your article at the begining
Yes! I know that, so I mention links in reference. Don't take it the negative way I'm just learning how to implement it on python flask. And just trying to put everything as a future reference as well as I think it can be helpful for others.
Thanks for your valuable comment.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.