DEV Community

Sudhakar Punniyakotti
Sudhakar Punniyakotti

Posted on

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.

Why flask?

We do have multiple choices to make a minimal API setup,

  1. NodeJS with Express
  2. Python with Flask or Django
  3. C# with .Net Core or
  4. 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 👀)

Python Flask

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

  1. System setup
  2. Project setup
  3. Implementation
  4. Testing the API's

Okey, lets start to code 🔥

1. System setup - prerequisites

Mac OS and Python 3.X, VS Code, Postgresql and Git.
Enter fullscreen mode Exit fullscreen mode

If you are using Ubuntu then the flow will be same but need to find the equivalent commands in installation.

2. Project setup

2.1 Install / Verify the python

brew install python
Enter fullscreen mode Exit fullscreen mode

Check the installation

python --version
Enter fullscreen mode Exit fullscreen mode

2.2 Install virtualenv

To manage the python and dependencies across the system at least on the dev environment we must use the virtualenv

pip install virtualenv
Enter fullscreen mode Exit fullscreen mode

2.3 Project initiation

Create a folder for the project

mkdir flash-sample
cd flask-sample
ls
__pycache__ env
Enter fullscreen mode Exit fullscreen mode

2.4. virtualenv initialization

python -m venv env
source env/bin/activate
Enter fullscreen mode Exit fullscreen mode

2.5 install SQL ORM

In this article, we will use sqlalchemy with PostgreSQL

pip install flask_sqlalchemy
pip install psycopg2
Enter fullscreen mode Exit fullscreen mode

2.6 Create project requirements

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
Enter fullscreen mode Exit fullscreen mode

2.7 Version control

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)
Enter fullscreen mode Exit fullscreen mode

Create gitignore file to remove the unwanted files tobe tracked and pushed to the repository

touch .gitignore
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

So the base code is ready now.

3. Implementation

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
Enter fullscreen mode Exit fullscreen mode

3.1 Import section

Import required modules

from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from flask import jsonify
Enter fullscreen mode Exit fullscreen mode

3.2 setup database configurations

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///hands_contact'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

3.3 Define the model

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
Enter fullscreen mode Exit fullscreen mode

3.4 Invoke the app

Let's create a module to run the application and set the database with models

if __name__ == '__main__':
  db.create_all()
  app.run()
Enter fullscreen mode Exit fullscreen mode

3.5 Create the users

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
Enter fullscreen mode Exit fullscreen mode

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'])
Enter fullscreen mode Exit fullscreen mode

3.6 List users

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)
Enter fullscreen mode Exit fullscreen mode

To be basic used the jsonify but to be more proper we can use the marshmallow serializer.

Import

from flask_marshmallow import Marshmallow
Enter fullscreen mode Exit fullscreen mode

Initialize

ma = Marshmallow(app)
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

4.Let's test now

Run the application from terminal

flask run
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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}]
Enter fullscreen mode Exit fullscreen mode

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!!!

Discussion (0)