Home Python alembic usage a migration tool for sqlalchemy
Post
Cancel

Python alembic usage a migration tool for sqlalchemy

This article will introduce basic usage about alembic for migration about SQLAlchemy.

I’m in windows 10 and python 3.11.2

Setup

I’m currently in a new folder named alembic-example folder.

Create a virtual environment for python.

1
python -m venv venv

Activate virtual environment

1
.\venv\Scripts\activate

Install dependencies.

1
pip install alembic psycopg2-binary

Run cmd alembic init {alembic_folder_name}

1
alembic init alembic

It will create a folder named alembic and a file named alembic.ini.


In alembic-example folder, create an app folder and create a file named database.py inside app folder.

In database.py, you need to configure your connection string CONNECTION_STR

1
2
3
4
5
6
7
8
9
10
import sqlalchemy
from sqlalchemy.orm import sessionmaker, declarative_base

# Config your connction string //{username}:{password}@{host}:{port}/{database}
CONNECTION_STR = 'postgresql+psycopg2://postgres:mysecretpassword@localhost:5432/postgres'

engine = sqlalchemy.create_engine(url=CONNECTION_STR)
SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)

Base = declarative_base()

In app folder, create a file named models.py.

In models.py, I simply import database.py’s Base and create a simple table.

1
2
3
4
5
6
7
8
from app.database import Base

import sqlalchemy as sa

class User(Base):
    __tablename__ = 'user'

    id = sa.Column(sa.Integer, primary_key=True, nullable=False)

And I also create a __init__.py in app folder.

Now, the folder’s structure should be similar like this:

1
2
3
4
5
6
7
8
alembic-example/
    alembic/
        ...
    alembic.ini
    app/
        __init__.py
        database.py
        models.py

Configure alembic

In alembic.ini, change sqlalchemy.url

from

1
sqlalchemy.url = driver://user:pass@localhost/dbname

to

1
sqlalchemy.url = postgresql+psycopg2://postgres:mysecretpassword@localhost:5432/postgres

In alembic/env.py, change

from

1
target_metadata = None

to

1
2
from app.models import Base
target_metadata = Base.metadata

Run alembic

Create a new version

Run alembic revision --autogenerate -m "{your simple description}"

1
alembic revision --autogenerate -m "First revision"

This will generate a migration script in alembic/revision/ folder and a table named alembic_version in database which will be used for controlling database version.

Migrate up

Run alembic upgrade +1 will upgrade database 1 version,

or run alembic upgrade head will upgrade database to newest version

1
alembic upgrade +1

Now the database create a table named user, a column id and an index for id

Modify table and migrate up

Add a new column username for user

Here is updated models.py

1
2
3
4
5
6
7
8
9
from app.database import Base

import sqlalchemy as sa

class User(Base):
    __tablename__ = 'user'

    id = sa.Column(sa.Integer, primary_key=True, nullable=False)
    username = sa.Column(sa.String, index=True)

Run

1
2
alembic revision --autogenerate -m "Add username for user"
alembic upgrade +1

refresh the database and see the result, it works.

Migrate down

Migrade down 1 version

1
alembic downgrade -1

Migrade down to the base

1
alembic downgrade base

Takeaway

I think the best pratice is:

  • when you migrate up you git commit the related model file
  • when you migrate down you rollback to related model file
1
2
3
4
5
alembic revision --autogenerate -m "First revision"
alembic upgrade +1
alembic upgrade head
alembic downgrade -1
alembic downgrade base
This post is licensed under CC BY 4.0 by the author.

Python utils tricks

Two dimensional img layout