- Published on
Quickstart Python REST APIs with Flask
- Authors
- Name
- jvip
- @PythonRoadmap
Table of Contents
Introduction
Namaste all 🙏, in this blog post we'll implement a REST APIs that performs the CRUD operations using Python framework Flask. CRUD is short for the following operations :
- Create : Creating a record in the underlying database
- Read : Reading records from database
- Update : Updating a record in database
- Delete : Deleting a record from database
Before we move ahead, make sure you are done with these steps :
- Python : Have python installed on your system. If you don't have it already, install the latest version of Python from this guide.
- PIP : Most likely you will have it installed with Python itself, make sure it's updated to latest version by running the following command :
pip install -U pip
- REST API Client : You'll need a client to make requests to the REST APIs that you are making. We recommend installing Postman, but if you are a power user, feel free to use cURL 🤓. We'll be using Postman for this article.
Installing Flask
Flask is a lightweight Python Framework built for rapid development and it is quite easy to use. Because flask
isn't a builtin python module, we'll need to install it on our system. You can do so with pip easily, by running the following command :
pip install flask
With this step, you will have Flask installed on your system, and can now move forward with writing actual code.
REST APIs with Flask
In all forms of web development, there are two components :
- Server : That will contain the logic, and take request as input and send response as output
- Client : That will make request to the server, and consume the response
With flask, we will be creating the server, that will contain the code for our APIs and will execute on client requests.
Creating a Flask server
Let's first create a simple flask server and an endpoint which will simply return "Hello World!". Create a file named app.py
and add the following code to simply create your hello world app in flask.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def quickstart():
return "Hello World!"
if __name__== '__main__':
app.run(
host="127.0.0.1",
port="8000"
)
To run the basic API server we just created, we need to run flask. We can do so by following these simple steps :
- Move to the directory where you created
app.py
file - Execute following command on your terminal / command prompt :Hit enter!
python app.py
- Now open Postman, and make a GET request to url
http://127.0.0.1:8000
- You'll see the text "Hello World!" for response.
You can change the port according to you by replacing 8000
with port number of choice.
Setting up a Database
For this tutorial, we will use a serverless, easy-to-use, relational database i.e sqlite3. You are free to use any database of your choice. Let's consider that we are making a blog app. So we'll want to create, read, update and delete the blog posts from our website. For keeping this example easy to understand, we'll create a table with following fields :
- id : to store a unique id for each blog post
- title : to store blog's title
- description : to store blog's content
- timestamp : to store created_at time of a blog post
Open your app.py
and update it with the following code :
from flask import Flask
import sqlite3
conn = sqlite3.connect("db.sqlite3")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS post (id VARCHAR(36), title VARCHAR(100), description LONGTEXT, created DATETIME)")
conn.commit()
cursor.close()
conn.close()
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
@app.route('/')
def healthcheck():
return "Hello World!!"
if __name__== '__main__':
app.run(
host="127.0.0.1",
port="8000"
)
With the above code, out flask app will create a table named post inside our SQLITE db if doesn't exist already.
Note : You don't need to install sqlite3 python library, as it's part of builtin libraries.
Creating Blog post create API
For creating a resource, it's industry standard to use POST
HTTP method. So, let's add the code for handling the POST request endpoint which will add the requested post sent inside the body of the request.
import uuid
from flask import Flask, request, jsonify
@app.route('/api', methods=['POST'])
def create_post():
data = request.get_json()
id = uuid.uuid4()
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute(f"insert into post (id, title, description, created) values ('{id}','{data['title']}','{data['description']}','{data['created']}')")
cursor.execute(f"select * from post where id='{id}'")
values = cursor.fetchall()
conn.commit()
cursor.close()
conn.close()
post = [dict(i) for i in values]
return jsonify({
"status": True,
"message": "Post is created successfully!",
"post": post
})
The above code will add the post inside the post
table in SQLITE and on successful execution this will return the post which is created with the unique id and the message "Post is created successfully!". Hit the endpoint http://127.0.0.1:8000/api with the post
request and with the body similar to this,
{
"title": "Dummy blog post!",
"description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
"created": "2022-10-10 12:00:00"
}
On making a request to the endpoint, you should get a response like this :
{
"status": true,
"message": "Post is created successfully!",
"post": [
{
"title": "Dummy blog post!",
"description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
"created": "2022-10-10 12:00:00"
}
]
}
Creating Blog post read API
For fetching a list/single resource, it's industry standard to use GET
HTTP method. To fetch all the records, add the following code which will simply return the list of posts inside the table.
import uuid
from flask import Flask, request, jsonify
@app.route('/api', methods=['GET'])
def list_posts():
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("select * from post")
values = cursor.fetchall()
cursor.close()
conn.close()
posts = [dict(i) for i in values]
return jsonify({
"status":True,
"posts":posts
})
The above code will get a list of all blog posts inside the post
table in SQLITE. Hit the endpoint http://127.0.0.1:8000/api with the get
request.
On making a request to the endpoint, you should get a response like this :
{
"status": true,
"posts": [
{
"title": "Dummy blog post!",
"description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
"created": "2022-10-10 12:00:00"
}
]
}
Creating Blog post update API
For update a resource, it's industry standard to use PUT
HTTP method. Now, to update the existing post this code below will do the trick.
import uuid
from flask import Flask, request, jsonify
@app.route('/api', methods=['PUT'])
def update_post():
data = request.get_json()
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute(f"update post set title='{data['title']}',description='{data['description']}',created='{data['created']}' where id='{data['id']}'")
cursor.execute(f"select * from post where id='{data['id']}'")
values = cursor.fetchall()
conn.commit()
cursor.close()
conn.close()
post = [dict(i) for i in values]
return jsonify({
"status":True,
"message":"Post is updated successfully!",
"post":post
})
The above code will update the blog post's title, description, created based on the blog post's id. Hit the endpoint http://127.0.0.1:8000/api with the put
request and with the body similar to this,
{
"id": "56ae506e-8ba7-46c5-853d-6924c89ab4e6",
"title": "how to correctly lorem ipsum",
"description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem perferendis pariatur nobis culpa voluptatem nam sunt sit repudiandae!",
"created": "2022-11-10 12:00:00"
}
On making a request to the endpoint, you should get a response like this :
{
"status": true,
"message": "Post is updated successfully!",
"post": [
{
"id": "56ae506e-8ba7-46c5-853d-6924c89ab4e6",
"title": "how to correctly lorem ipsum",
"description": "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem perferendis pariatur nobis culpa voluptatem nam sunt sit repudiandae!",
"created": "2022-11-10 12:00:00"
}
]
}
Creating Blog post delete API
To delete a resource, it's industry standard to use DELETE
HTTP method. Let's code the endpoint for deleting our blog post.
@app.route('/api', methods=['DELETE'])
def delete_post():
data = request.get_json()
conn = sqlite3.connect("db.sqlite3")
cursor = conn.cursor()
cursor.execute(f"delete from post where id='{data['id']}'")
conn.commit()
cursor.close()
conn.close()
return jsonify({
"status":True,
"message":"Post is deleted successfully!"
})
The above code will will delete a post from the database table based on the blog post's id specified in request body. Hit the endpoint http://127.0.0.1:8000/api with the delete
request and with the body similar to this,
{
"id": "56ae506e-8ba7-46c5-853d-6924c89ab4e6"
}
On making a request to the endpoint, you should get a response like this :
{
"status": true,
"message": "Post is deleted successfully!"
}
Frequently Asked questions
Is Flask harder than Django ?
Flask is easier to learn than Django. Flask is a microframework, which means it doesn't have a lot of features that are included by default in Django. This makes it easier and faster to learn.
Is Flask a microservice ?
Flask is not a microservice. However, you can use Flask to build microservices.
Why is Flask so popular ?
It has many reasons for being popular. Flask is very easy to learn, it's lightweight, fast and easy to deploy as well.
Is flask suitable for production ?
Yes! Flask is suitable for production as well. Many companies have been using Flask in production for years.
Which companies use Flask ?
Flask is used by companies like Netflix, reddit, CRED, trivago, etc.
Ending Notes
And that's it, this is how easy and simple it is to create a REST API for CRUD operations in Flask. There is also a flask-restful
library which abstracts some of the hassles with plain flask for you. We recommend exploring it as well.
We've added the complete code for this exercise in the end. Happy Learning!
Flask CRUD REST APi Boilerplate
After all the endpoints we've made, this is how the final app.py
should look like. You can use this as CRUD API boilerplate as well.
import sqlite3
import uuid
from flask import Flask, request, jsonify
conn = sqlite3.connect("db.sqlite3")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS post (id VARCHAR(36), title VARCHAR(100), description LONGTEXT, created DATETIME)")
conn.commit()
cursor.close()
conn.close()
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
@app.route('/')
def healthcheck():
return "Hello World!!"
@app.route('/api', methods=['POST'])
def create_post():
data = request.get_json()
id = uuid.uuid4()
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute(f"insert into post (id, title, description, created) values ('{id}','{data['title']}','{data['description']}','{data['created']}')")
cursor.execute(f"select * from post where id='{id}'")
values = cursor.fetchall()
conn.commit()
cursor.close()
conn.close()
post = [dict(i) for i in values]
return jsonify({
"status": True,
"message": "Post is created successfully!",
"post": post
})
@app.route('/api', methods=['GET'])
def list_posts():
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("select * from post")
values = cursor.fetchall()
cursor.close()
conn.close()
posts = [dict(i) for i in values]
return jsonify({
"status":True,
"posts":posts
})
@app.route('/api', methods=['PUT'])
def update_post():
data = request.get_json()
conn = sqlite3.connect("db.sqlite3")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute(f"update post set title='{data['title']}',description='{data['description']}',created='{data['created']}' where id='{data['id']}'")
cursor.execute(f"select * from post where id='{data['id']}'")
values = cursor.fetchall()
conn.commit()
cursor.close()
conn.close()
post = [dict(i) for i in values]
return jsonify({
"status":True,
"message":"Post is updated successfully!",
"post":post
})
@app.route('/api', methods=['DELETE'])
def delete_post():
data = request.get_json()
conn = sqlite3.connect("db.sqlite3")
cursor = conn.cursor()
cursor.execute(f"delete from post where id='{data['id']}'")
conn.commit()
cursor.close()
conn.close()
return jsonify({
"status":True,
"message":"Post is deleted successfully!"
})
if __name__== '__main__':
app.run(
host="127.0.0.1",
port="8000"
)