Simplify Your REST API Development with Flask, SQLAlchemy, and Docker

Sunday, 21 May 2023 6 minutes read

What Are We Going To Build

In today's world, building a scalable and performant REST API is crucial for any modern web application. Although planning and developing such solution requires time, we often need to code something really fast for a proof of concept. In this blog I'll use Flask framework and it's extension Flask-RESTful to quickly build an REST API for a ToDo application. We will use SQLite as data base and SQLAlchemy for the ORM. We will use Flask-SQLAlchemy extension for SQLAlchemy support into Flask. Finally, we will dockerize our ToDo web applicaiton. 

Planning & Coding The Project

Our web applicaiton will be very simple. We save our todo tasks in the database and retrive them. We need to create:

  • A POST Api to save a task into the database.
  • A GET Api to retrive the tasks.

So we will use a model class Task and create these two API's around it.

Project Structure

We will sturcture our project like bellow: 

todo-project/
  todoapp/
    __init__.py
    models.py
    schemas.py
    views.py
  requirements.txt
  venv/
  .flaskenv

Prepare the Development Environment

To begin, we will create the project folder todo-project. Inside this folder, we need to set up a virtual environment called venv and activate it. Please note that the following example is for a Linux-based system, and the commands may vary slightly for Windows.

~ $ pip install virtualenv
~ $ cd todo-project
todo-project $ virtualenv venv
todo-project $ source venv/bin/activate

Now we need to install the required packages for this project. The requirements.txt file for this is:

Each package can be installed separately or this file can be copied and all required packages can be installed in a single command.

(venv)todo-project $ pip install -r requirements.txt

Building The Todo App

We will add a Python package named todoapp inside the todo-project directory. A Python package is simply a directory that contains an __init__.py file. While this file is often empty in many packages, in our project structure, the __init__.py file plays an important role. We will use it to initialize the core components, such as the Flask application and SQLAlchemy database.

In this file, we are primarily responsible for initializing various components of the project. The database URI will create the todo.db file in the parent directory of the todoapp directory. To use the flask run command, we need to create a .flaskenv file in the todo-project directory. In this file, we will define the required environment variables. The flask run command relies on the FLASK_APP environment variable to determine the name of the file that contains the Flask application. In our case, the Flask application is contained in the __init__.py file of the todoapp package, so we can set FLASK_APP=todoapp here. Additionally, we will utilize another environment variable, FLASK_RUN_HOST=0.0.0.0, to ensure that the app is externally visible.

Our models.py file consists of a single model named Task, which represents a task in our application.

We have used Flask-SQLAlchemy to define our table and columns. For serializing and deserializing data, we will be using Marshmallow. Similar to SQLAlchemy, Flask also has an integration package with Marshmallow called Flask-Marshmallow, which we will utilize. We will add a schemas.py file in the todoapp directory, where we will define our TaskSchema.

We will now create the API endpoints by adding another file called views.py inside the todoapp directory. In this file, we will define a Resource class called TaskResource. In Flask-RESTful, a Resource class represents an entity or a collection of entities that can be exposed through an API. This class provides a set of methods that can be overridden to define the behavior of the resource for different HTTP methods such as GET, POST, PUT, DELETE, and more. Since we are only interested in creating a todo task and retrieving tasks, we will be overriding the get and post methods.

Our API is ready now and we can run it with command flask run. There is a single endpoint /api/todo for creating and retrieving tasks.

Dockerizing The Project

Dockerizing a project means packaging your application, along with its dependencies and configurations, into a Docker container. For Dockerizing the first we need to create a Dockerfile. We will create this into the todo-project directory.

We will build our Docker image using the python:3.10-alpine base image. Within the container, we will set the working directory to /app and copy our requirements.txt file, installing the necessary dependencies. Next, we'll copy all the files from our existing directory into the /app directory. If there are any files we want to exclude, we can specify them in a .dockerignore file. Finally, we'll execute the flask run command to start the application.