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.