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
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
| Steps | Command | Function | Django equivalent |
|---|---|---|---|
| Initialize | flask db init | Create a migrations/ directory (execute only once). | — |
| Generate | flask db migrate -m "description" | Detect model changes and generate migration scripts. | makemigrations |
| Execute | flask db upgrade | Apply 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
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
| Operation | Flask(Flask-Migrate) | Django |
|---|---|---|
| Initialize | flask db init | Not needed (the project comes with a migrations directory). |
| Generate migration | flask db migrate -m "description" | python manage.py makemigrations |
| Execute migration | flask db upgrade | python manage.py migrate |
| Rollback | flask db downgrade | python manage.py migrate app 0001 |
| View history | flask db history | python manage.py showmigrations |
| Degree of automation | Initialization 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