Database Migrations with sqlmodel and alembic
python, databases
sqlmodel is a very useful proxy tool that allows pydantic models and sqlalchemy models to be combined. This allows FastAPI, built by the same author, to intuitively know more about the models' metadata.
This guide will show you how to combine this tool into alembic, and create auto-migrations with a set of helper tools.
The Setup
We will need 2 functions in 2 files, which are pretty simple. The first is the engine creator.
1 2 3 4 5 6 7
# database.py from sqlmodel import create_engine from sqlalchemy.engine import Engine def get_db_engine(url) -> Engine: return create_engine(url)
Which will create the SQLAlchemy Engine object for us. This is used for alembic to connect to the database, I also use this function, cached, to generate Session objects. The next is used for the models.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# model.py import uuid from typing import Optional from sqlmodel import Field, SQLModel class Hero(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str secret_name: str age: Optional[int] = None def get_metadata(): return SQLModel.metadata
This file contains all our models, registering the metadata as tables, relationships, indexes and anything else that's
constructed. The get_metadata()
method must be after the model definitions so the SQLModel.metadata
is complete.
From here we can touch the alembic env.py function to describe the online environment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from myapp.database import get_db_internal from myapp.model import get_metadata ... # `context` defined as before target_metadata = get_metadata() def run_migrations_online() -> None: connectable = get_db_internal() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata ) with context.begin_transaction(): context.run_migrations()
The important bit here is the connection and metata are fetched directly from your application via the imports. This will set up all the correct connection details for the environment. To create production migrations you will have to generate the migrations on a host with access the prod environment (i.e. script opening a PR from a prod env).
The Execution
Now we can continue from normal, running alembic revision --autogenerate
to create revisions on the delta of the
database & metadata Models. Running this will create a new version in the correct directory.
At this point you may need to manually import sqlmodel
to link together column types. Other changes should be made
at this point.
Then running alembic upgrade head
will update the database up to the correct revision.