Flask-Migrate — Database Migrations

In this chapter you will learn how to safely manage database schema changes with Flask-Migrate, and understand how it corresponds to Django migrations.


Why can't we always use db.create_all()?

db.create_all()There are two fatal flaws:

  • Only creates when the table doesn't exist. Modifying the model (e.g., adding new fields) will not update existing tables.
  • No change history is kept. You cannot roll back to a previous database state.

Database MigrationsJust like Git for databases—every schema change generates a version file, supporting upgrades and rollbacks.

Flask-MigrateIt is a Flask extension for Alembic, designed specifically for SQLAlchemy.


Installation and Configuration

(venv) $ pip install flask-migrate

Example

# File path: app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'

db = SQLAlchemy(app)
migrate = Migrate(app, db)    # Bind app and db to Migrate

Migration in three steps

StepsCommandFunctionDjango equivalent
Initializeflask db initCreate a migrations/ directory (execute only once).—
Generateflask db migrate -m "description"Detect model changes and generate migration scripts.makemigrations
Executeflask db upgradeApply the migration scripts to the database.migrate

Step 1: Initialize the migration directory

(venv) $ flask db init
Creating directory migrations/...  done

Generated after executionmigrations/Directory (similar to Git's .git directory), only needs to be executed once.

Step 2: Generate migration files.

(venv) $ flask db migrate -m "初始化 Post 和 Category 模型"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
Generating migrations/versions/xxxx_initial.py ... done

If you don't have any model changes yet, simply run this command on an existing model.

Step 3: Execute migrations.

(venv) $ flask db upgrade
INFO  [alembic.runtime.migration] Running upgrade  -> xxxx, 初始化

Hands-on: add a new field to the Post model.

Suppose the product requirements change and you need to add a read count to the article.

Example

# File path: added in the Post class of models.py
class Post(db.Model):
    # ... existing fields ...
    read_count = db.Column(db.Integer, default=0)  # New: read count

After modifying the model, execute migrations:

(venv) $ flask db migrate -m "Post 模型新增 read_count 字段"
(venv) $ flask db upgrade

Now in the databasepostsThe table has been automatically addedread_countColumns, existing data is not affected.

View the migration history

Check which version the current database is at:

(venv) $ flask db current

View all migration history:

(venv) $ flask db history

Rollback migration

Migrations can be rolled back:

(venv) $ flask db downgrade   # 回退到上一个版本

This will deleteread_countColumn, undo all changes from the last migration.

Not all operations can be rolled back automatically (such as dropping a column in SQLite). Confirm before rolling back.flask db currentCheck the current version to ensure you know what you are rolling back. Always back up data before rolling back in production.


Flask-Migrate vs Django Migration Comparison

OperationFlask(Flask-Migrate)Django
Initializeflask db initNot needed (the project comes with a migrations directory).
Generate migrationflask db migrate -m "description"python manage.py makemigrations
Execute migrationflask db upgradepython manage.py migrate
Rollbackflask db downgradepython manage.py migrate app 0001
View historyflask db historypython manage.py showmigrations
Degree of automationInitialization is required; it detects the Alembic dependency.Fully automatic, no additional configuration required.

Django's migration system is more automated and more integrated; Flask achieves the same level of capability through Flask-Migrate.


Chapter summary

In this chapter, you mastered the complete Flask-Migrate workflow: flask db init initializes, flask db migrate generates migration scripts, flask db upgrade applies migrations, and flask db downgrade rolls back.

From now on, every time you modify models.py, follow this three-step workflow, and database schema changes will always have traceable history.

other extensions