22
A simple API application using Python & Flask
How to create a simple API application with minimal learning and clean code for beginners.
Most of the times developers create a simple frontend application that needs a couple of API's but to do that they might rely on the backend team or mock API tools like Postman or create their own.
So let us write a tiny application which covers this requirement.
We do have multiple choices to make a minimal API setup,
- NodeJS with Express
- Python with Flask or Django
- C# with .Net Core or
- Ruby on Rails.
We can use any of the above but I am an old friend of Ruby on Rails so chose Python with Flask for a bare minimum code. ( Actually less than 50 lines 👀)
This article doesn't intended to be production-ready code, but to make quick APIs with a database for beginners.
What we are going to cover
- System setup
- Project setup
- Implementation
- Testing the API's
Okey, lets start to code 🔥
Mac OS and Python 3.X, VS Code, Postgresql and Git.
If you are using Ubuntu then the flow will be same but need to find the equivalent commands in installation.
brew install python
Check the installation
python --version
To manage the python and dependencies across the system at least on the dev environment we must use the virtualenv
pip install virtualenv
Create a folder for the project
mkdir flash-sample
cd flask-sample
ls
__pycache__ env
python -m venv env
source env/bin/activate
In this article, we will use sqlalchemy with PostgreSQL
pip install flask_sqlalchemy
pip install psycopg2
python -m pip freeze requirements.txt
click==8.0.1
Flask==2.0.1
Flask-SQLAlchemy==2.5.1
greenlet==1.1.1
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
psycopg2==2.9.1
SQLAlchemy==1.4.25
Werkzeug==2.0.1
We will use the git as version control and let's initialize
git init.
Initialized empty Git repository in /PROJECT_FOLDER/.git/
git s
On branch master
No commits yet
Untracked files:
(use "git add file..." to include in what will be committed)
env/
requirements.txt
nothing added to commit but untracked files present (use "git add" to track)
Create gitignore file to remove the unwanted files tobe tracked and pushed to the repository
touch .gitignore
Add the standard gitignore file from here and make sure you add the virtualenv folder name in the gitignore.
git add.
git commit -m "Initial commit"
So the base code is ready now.
As mentioned earlier in this article we are going to add two rest API endpoints to save and retrieve data using Postgresql.
Create the python file to handle our API's
touch app.py
Import required modules
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask import jsonify
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///hands_contact'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
If PostgreSQL running in a remote location then we can add the URL along with user name and password like
'postgresql://usernamr:password@server/database_name'
Let's create a user model
class SampleUser(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(80), nullable=False)
last_name = db.Column(db.String(120), nullable=False)
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
Let's create a module to run the application and set the database with models
if __name__ == '__main__':
db.create_all()
app.run()
def creation():
content=request.get_json(silent=True)
try:
db.session.add(SampleUser(content["first_name"],
content["last_name"]))
db.session.commit()
return'Ok', 200
exceptExceptionase:
return'Invalid request', 400
The request will be converted into JSON and required parameters are loaded from there to create the user.
Finally, mound this method into the route using
@app.route("/create_users", methods=['POST'])
Similar to the creation let's create a get users route as GET method.
@app.route('/users', methods=['GET'])
def home():<br /> data = []
for user in SampleUser.query.all():
data.append(
{ "id": user.id,
"first_name": user.first_name,
"last_name": user.last_name
})
return jsonify(total_users_count=len(data), data=data, status=200)
To be basic used the jsonify but to be more proper we can use the marshmallow serializer.
Import
from flask_marshmallow import Marshmallow
Initialize
ma = Marshmallow(app)
Setup a schema that defined what are the columns needs to be constructed in JSON
class SampleUserSchema(ma.Schema):
class Meta:
fields = ("id", "first_name")
sample_user_schema = SampleUserSchema()
sample_user_schema = SampleUserSchema(many=True)
Now update the get users method.
@app.route('/users', methods=['GET'])
def listing():
all_notes = SampleUser.query.all()
return jsonify(sample_user_schema.dump(all_notes)), 200
that's it! so simple isn't it? The complete code for convenience below
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask import jsonify
# Database ORM Configs
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///hands_contact'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
ma = Marshmallow(app)
# User model for contact us
class SampleUser(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(80), nullable=False)
last_name = db.Column(db.String(120), nullable=False)
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
# JSON response serializer
class SampleUserSchema(ma.Schema):
class Meta:
fields = ("id", "first_name")
sample_user_schema = SampleUserSchema()
sample_user_schema = SampleUserSchema(many=True)
# Simple Dashboard
@app.route('/users', methods=['GET'])
def listing():
all_notes = SampleUser.query.all()
return jsonify(sample_user_schema.dump(all_notes)), 200
# Contact us POST API
@app.route("/create_users", methods=['POST'])
def creation():
content = request.get_json(silent=True)
try:
db.session.add(SampleUser(content["first_name"], content["last_name"]))
db.session.commit()
return 'Ok', 200
except Exception as e:
return 'Invalid request', 400
# Invoke the application
if __name__ == '__main__':
db.create_all()
app.run()
Run the application from terminal
flask run
The default port for flask application is 5000 and applictaion will be listening to http://127.0.0.1:5000.
Create users using the POST endpoint /create_users with the payload
curl -X POST -d '{ "first_name": "Badsha", "last_name": "Manik" }' http://127.0.0.1:5000/create_users -H 'Content-Type: application/json' -H 'Accept: application/json'
Ok
List users using GET endpoint /users
curl http://127.0.0.1:5000/users
[{"first_name":"Vijay","id":1},{"first_name":"" 1","id":2},{"first_name":"Ajith","id":3}]
So as a starting point this single file serves the purpose but for production, as per required patterns you can split the configs, serializer, models and API methods and import wherever required.
References,
https://flask.palletsprojects.com/en/2.0.x/
https://flask.palletsprojects.com/en/2.0.x/api/
https://flask-marshmallow.readthedocs.io/en/latest/
Thank you for your time and happy learning!!!
22