How to Use Alembic for Database Migrations in Your FastAPI Application
- FastAPI
- SQLAlchemy
- Alembic
Download the PDF version of this post for free:
Introduction
When building a FastAPI application, managing database schema changes can be a daunting task. As your application evolves, your database schema must adapt to accommodate new features, bug fixes, and changing requirements.
Alembic is a lightweight and flexible database migration tool that simplifies the process of managing database schema changes. By using Alembic, you can track changes to your database schema, revert to previous versions, and collaborate with your team more effectively.
In this tutorial, I will show you how to use Alembic for database migrations in a FastAPI application by building the project from scratch. I will be using PostgreSQL as the database server, but you should be able to follow this tutorial by using any database server.
By the end of this tutorial, you will have:
- A complete working CRUD API.
- Knowledge to make changes to your models and apply database migrations.
Setup a new project
We will create a new project from scratch. It is recommended to create new virtual environment to isolate your project’s dependencies from the system Python environment.
Create and activate a new virtualenv:
Install the required packages:
Note that I installed psycopg2-binary
for PostgreSQL. If you are using a different database server, you should install the corresponding database driver. For example, install mysql-connector-python
if you are using MySQL.
Create the src/ directory and make it a package:
Your directory structure should look like this:
. ├── requirements.txt └── src └── __init__.py
We will put all of our database and FastAPI code in the src/ directory.
Create the SQLAlchemy model
We will setup the database connection in src/database.py file and define our model in src/models.py file. By separating the database connection and models definition, we can maintain a clean and modular architecture for our FastAPI application.
Create a new file named src/database.py and add the following code:
The code above sets up a connection to a PostgreSQL database using SQLAlchemy. The connection string is hardcoded in the file just to make it simpler. To add more security layer, you can load the connection string from environment variables instead.
Now we write the SQLAlchemy model. Create a new file named src/models.py and add the following code:
After we have created the model, we want to automate the database migration using Alembic.
Using Alembic for database migration
We use Alembic to automate database migrations, which involves managing changes to the database schema over time.
Start by initializing Alembic:
The command above will create the alembic/ directory with the necessary configuration files. After you run this command, your directory structure will look like this:
. ├── alembic │ ├── README │ ├── env.py │ ├── script.py.mako │ └── versions ├── alembic.ini ├── requirements.txt └── src ├── __init__.py ├── database.py └── models.py
From all of the files generated by Alembic, you only need to modify the alembic/env.py file. This file is a Python script that serves as the entry point for Alembic’s migration process. It’s responsible for setting up the environment, loading the configuration, and executing the migration scripts.
Open alembic/env.py and find the line that contains:
And replace it with:
By importing Base
from src.models
and setting target_metadata
to Base.metadata
, we are configuring Alembic to work with your SQLAlchemy models. Alembic will generate the proper migration scripts by reading our model’s metadata.
Below those lines, add the following code as well:
By importing the DATABASE_URL
variable and setting the sqlalchemy.url
option, we are configuring Alembic to connect to our database using the specified connection string. It allows us to specify the connection string in the environment variables instead of hardcode it in the alembic.ini
file.
Create the database migration script:
And run the database migration:
After you run the command, you should see the “items” table is created in your PostgreSQL database.
Create the API endpoints
To create the API endpoints using FastAPI, we’ll start by writing the Pydantic models. These models are used to serialize data into JSON and perform data validation. It is also being used in the responses where the data is converted into JSON format.
Open src/schemas.py and add the following code:
In the code above, we created 3 Pydantic models: Item
will be used as a response model for API endpoints that return a single item or a list of items, ItemCreate
and ItemUpdate
will be used to ensure that data is validated and sanitized when creating or updating items.
Now that the models are ready, we can write the API endpoints to create, read, update, and delete the items. Open src/main.py and add the following code:
The code above provides the API endpoints to perform CRUD (Create, Read, Update, Delete) operations for the items and is self-explanatory.
Making new changes to the model
Lets say you want to make some changes to the model and you want Alembic to generate the migration script to alter the database. As an example, lets add a new “quantity” column.
Open src/models.py and add the column:
The new line tells SQLAlchemy that the quantity column is of type int
, and set the default value to 0 if no value is provided when inserting a new row. It will also set the value to 0 for existing rows.
Add the same field to the Pydantic model so the API will return the item’s quantity as well. Open src/schemas.py and add the field:
Create and run the database migration:
After you run the command, the table in your PostgreSQL database should have the “quantity” column. The field will also be returned in the API responses as well.
Download the PDF version of this post for free: