CRUD REST APIs in 5 Minutes Using Flask

Use Flask AppBuilder to develop CRUD REST APIs.

Flask API Development

Overview

For Python, when it comes to API development, we have an abundance of choices. Popular ones are Django, Flask, and FastAPI, to name a few.

In this article, let’s use Flask to build RESTful APIs to create, read, update and delete (CRUD) records in a database table. Specifically, I will use Flask + Flask AppBuilder to build the APIs in 5 minutes.

Setup

Libraries

Let’s install the flask-appbuilder library. I also installpython-dotenv in order to use a .env file as my configuration file.

$ pip install flask-appbuilder python-dotenv

Using a virtualenv will be preferred. I assume you are already familiar with Python and will not go through the steps here. For me, I prefer to use Minconda to manage all my packages.

PostgreSQL

For this example, I am going to use PostgreSQL. The docker-compose file is shown below.

docker-compose.yml

As part of the database setup, a database table called accounts is created.

CREATE TABLE accounts (
userid SERIAL PRIMARY KEY,
username VARCHAR (50) UNIQUE NOT NULL,
password VARCHAR (50) NOT NULL,
email VARCHAR (255) UNIQUE NOT NULL,
createdon TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
lastlogin TIMESTAMP
);

The database credentials are in the .env file

POSTGRES_USER=user1
POSTGRES_PASSWORD=userpwd
POSTGRES_DB=testdb
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
SECRET_KEY=9e9b7b01-ae3e-433d-b2ea-c93a69d77802

Application Setup

Create the App

Let’s create the application now using Flask AppBuilder.

$ flask fab create-app
Your new app name: flask-api
Your engine type, SQLAlchemy or MongoEngine (SQLAlchemy, MongoEngine) [SQLAlchemy]:
Downloaded the skeleton app, good coding!

Change Config to Use PostgreSQL

Now open config.py and change the configurations to use PostgreSQL.

import os
from dotenv import load_dotenv, find_dotenv
from flask_appbuilder.security.manager import (
AUTH_OID,
AUTH_REMOTE_USER,
AUTH_DB,
AUTH_LDAP,
AUTH_OAUTH,
)
basedir = os.path.abspath(os.path.dirname(__file__))# Load default .env file
load_dotenv(find_dotenv())
# Your App secret key
SECRET_KEY = os.getenv("SECRET_KEY")
# The SQLAlchemy connection string.
SQLALCHEMY_DATABASE_URI = f"postgresql://{os.getenv('POSTGRES_USER')}:{os.getenv('POSTGRES_PASSWORD')}@{os.getenv('POSTGRES_HOST')}/{os.getenv('POSTGRES_DB')}"

Setup the Application

Now let’s proceed to set up the application.

$ export FLASK_APP=app
$ flask fab create-admin
Username [admin]:
User first name [admin]:
User last name [user]:
Email [admin@fab.org]:
Password:
Repeat for confirmation:

Flask AppBuilder is now configured and the default admin user is created.

Flask AppBuilder with PostgreSQL

Application Code

Create the Model

Now open models.py and add the Accounts model.

from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()class Accounts(Base):
__tablename__ = 'accounts'
userid = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
email = Column(String)
createdon = Column(DateTime, default=datetime.datetime.utcnow)
lastlogin = Column(DateTime)

Define the APIs

Open views.py and add the APIs.

from flask_appbuilder import ModelView, ModelRestApi
from .models import Accounts
from . import appbuilder, db
class AccountsModelApi(ModelRestApi):
resource_name = 'accounts'
datamodel = SQLAInterface(Accounts)
appbuilder.add_api(AccountsModelApi)

Test APIs using Swagger

In config.py, add this line to enable Swagger UI.

FAB_API_SWAGGER_UI = True

Now I can run the Flask application.

$ flask run
....
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
2021-04-03 11:55:50,887:INFO:werkzeug: * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Using the URL http://localhost:5000/swagger/v1 I can now see the APIs documentation. You may need to log in using the admin user created earlier.

Swagger UI

Testing

Authentication

The APIs are protected by default. You can configure the APIs for public access by granting the permissions to the Public role.

APIs Permissions

If you do not want to open it for public access, you will need to obtain an authorization token in order to use the APIs.

From Swagger UI, use the /security/login endpoint to obtain a token.

Security Login Endpoint
Token for APIs

You can see the corresponding curl command that can be used to call the APIs.

Testing using curl

First, let’s obtain an access token and export it as an environment variable.

$ curl -XPOST http://localhost:5000/api/v1/security/login -d \
'{"username": "admin", "password": "admin", "provider": "db"}' \
-H "Content-Type: application/json"
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTc0MzIwMzMsIm5iZiI6MTYxNzQzMjAzMywianRpIjoiOThiYmNkZDQtMTc3ZS00YzZjLThlZjgtYWMxZWM1NmU4ZThlIiwiZXhwIjoxNjE3NDMyOTMzLCJpZGVudGl0eSI6MSwiZnJlc2giOnRydWUsInR5cGUiOiJhY2Nlc3MifQ.QVju851X6R9HohEBZphn-wjeVxpngEumn5urgyVdkbM"}$ export TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTc0MzIwMzMsIm5iZiI6MTYxNzQzMjAzMywianRpIjoiOThiYmNkZDQtMTc3ZS00YzZjLThlZjgtYWMxZWM1NmU4ZThlIiwiZXhwIjoxNjE3NDMyOTMzLCJpZGVudGl0eSI6MSwiZnJlc2giOnRydWUsInR5cGUiOiJhY2Nlc3MifQ.QVju851X6R9HohEBZphn-wjeVxpngEumn5urgyVdkbM

Let’s create an account using the token.

$ curl -XPOST http://localhost:5000/api/v1/accounts/ -d \
'{"username": "alpha2phi", "email": "alpha2phi@gmail.com", "password": "mypassword"}' \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN"
{"id":1,"result":{"createdon":"2021-04-03T06:58:54.493960","email":"alpha2phi@gmail.com","lastlogin":null,"password":"mypassword","username":"alpha2phi"}}

Retrieve the accounts.

$ curl  http://localhost:5000/api/v1/accounts/ -H "Authorization: Bearer $TOKEN"{"count":1,"description_columns":{},"ids":[1],"label_columns":{"createdon":"Createdon","email":"Email","lastlogin":"Lastlogin","password":"Password","username":"Username"},"list_columns":["username","password","email","createdon","lastlogin"],"list_title":"List Accounts","order_columns":["username","password","email","createdon","lastlogin"],"result":[{"createdon":"2021-04-03T06:58:54.493960","email":"alpha2phi@gmail.com","lastlogin":null,"password":"mypassword","username":"alpha2phi"}]}

Writing a Test Client

Let’s change the permission now to allow public access. I am going to write a simple Javascript test client which

  • Use the faker.js library to insert fake accounts.
  • Search for a particular account using email.
// Insert fake accounts
const faker = require("faker");
const axios = require('axios');
for (i = 0; i < 15; i++) {
axios.post('http://localhost:5000/api/v1/accounts', {
username: faker.name.findName(),
email: faker.internet.email(),
password: faker.internet.password()
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
// Search for alpha2phi
var filter = {};
filter.col = "email";
filter.opr = "eq";
filter.value = "alpha2phi@gmail.com";
var filters = [];
filters.push(filter);
filters_criteria = JSON.stringify({"filters" : filters});
console.log(encodeURI(filters_criteria));
const query = "http://localhost:5000/api/v1/accounts/?q=" + encodeURI(filters_criteria)
axios.get(query)
.then(response => {
console.log(response.data);
// console.log(response.data.explanation);
})
.catch(error => {
console.log(error);
});

You can read more about the filter criteria from the Swagger documentation using the “_info” endpoint.

Javascript Test Client

Summary

I only scratch the surface of features forFlask + Flask App Builder. For the APIs, you can also perform searching, filtering, create custom filters, define what columns to search and return, etc. Read the documentation and try it out yourself.

The source code I use in this article can be found in this repository.

Do also check out the following articles!

Programmer and occasional blogger.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store