Migrations
- encapsulate a set of changes to our database schema, made over time.
- are uniquely named
- are usually stored as local files in our project repo, e.g. a migrations/ folder
- migrations/
- add_tables_0001.py
- add_column_to_todos_0002.py
- rename_column_to_todos_0003.py
- The existence of the physical migration file indicates the changes made to the database.
- migrations/
- There should be a 1-1 mapping between the changes made to our database, and the migration files that exist in our migrations/folder
- Our migrations files set up the tables for our database
- All changes made to our db should exist physically as part of migration files in our repository.
Migration command line scripts
There are generally 3 scripts needed for
- create a migration script template to fill out; generating a migration file based on changes to be made
$ db migrate
- applying migrations that hadn’t been applied yet (“upgrading” our database)
$ db upgrade
- rollback applied applied migrations that were problematic (“downgrading” our database)
$ db downgrade
For Flask
- Flask-Migrate (flask_migrate) is our migration manager for migrating SQLAlchemy-based database changes. It is our library for migrating changes using SQLAlchemy. It uses a library called Alembic underneath the hood.
- Flask-Script (flask_script) lets us run migration scripts we defined, from the terminal
Steps to get migration going
- Initialize the migration repository structure for storing migrations.
- Create a migration script (using Flask-Migrate)
- (Manually) Run the migration script (using Flask-Script)
Without Flask-Migrate
# In app.py: db.create_all()
# To modify our models:
class Todo(db.Model):
completed = db.Column(...)
# Drop existing tables:
$ dropdb todoapp && createdb todoapp
# Recreate tables with the newly modified models: db.create_all()
Not great:
- We lose any existing data in our old tables
- Creating and re-creating entire tables, when we just wanted to add a column. We do heavy-handed work.
With Flask-Migrate
- Auto-detects changes from the old version & new version of the SQLAlchemy models
- Creates a migration script that resolves differences between the old & new versions
- Gives fine-grain control to change existing tables
- Much better
- We can keep existing schema structures, only modifying what needs to be modified
- We can keep existing data.
- We isolate units of change in migration scripts that we can roll back to a “safe” db state.
Alembic is the library that Flask-Migrate uses underneath for running migrations.
Flask-Migrate autodetects changes in our SQLAlchemy models, but we still have to manually run the migrations ourselves (using Flask-Migration underneath)
Migrations are physical files typically stored in our local repository that captures sets of changes to our database schema.
Flask-Script is an essential library for running migrations from Flask-Migrate.