Why Database Migrations Are Needed?¶
When developing web applications, database structures (such as table schemas and field types) may need adjustments as requirements evolve. Directly modifying database files (e.g., SQL files) can lead to data loss or version conflicts in collaborative environments. Database migration tools serve the purpose of safely altering database structures while preserving existing data, acting like “version control for your database.”
What is Flask-Migrate?¶
Flask-Migrate is a tool within the Flask ecosystem that simplifies database migrations. Built on top of Alembic (SQLAlchemy’s migration framework), it specifically manages database schema changes in Flask applications using SQLAlchemy. It automatically generates migration scripts and applies them to the database, eliminating the need to write SQL statements manually.
Installation and Initialization¶
1. Install Dependencies¶
First, ensure Flask and Flask-SQLAlchemy (the database ORM tool) are installed, then install Flask-Migrate:
pip install flask flask-sqlalchemy flask-migrate
2. Initialize Flask App and Database¶
Create a simple Flask application (e.g., app.py) and initialize the database and migration tool:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# Initialize Flask app
app = Flask(__name__)
# Configure database (SQLite example; replace with MySQL/PostgreSQL as needed)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Disable unnecessary modification tracking
# Initialize SQLAlchemy
db = SQLAlchemy(app)
# Initialize Flask-Migrate (must run after db)
migrate = Migrate(app, db)
# Define models (model changes will be demonstrated later)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
if __name__ == '__main__':
app.run(debug=True)
Core Migration Commands (Must-Learn!)¶
Flask-Migrate uses the Flask CLI for migrations. First, set the environment variable to specify your app entry point:
# Linux/Mac
export FLASK_APP=app.py # Replace with your app's filename
# Windows (PowerShell)
$env:FLASK_APP = "app.py"
Then use the following commands:
1. Initialize Migration Environment (First Time Only)¶
When using Flask-Migrate for the first time, initialize a folder to store migration scripts:
flask db init
This creates a migrations folder in your project root, containing configuration files and script templates for migrations.
2. Generate Migration Scripts¶
After modifying a database model (e.g., adding/removing fields), generate a migration script to describe the changes:
flask db migrate -m "Description of changes"
-mparameter: Required, used to describe the migration purpose (e.g.,"add age field to User model").- After execution, a Python file (e.g.,
xxxxxxxx_add_age_field_to_user_model.py) will appear inmigrations/versions, containing the SQL statements for the model changes.
3. Apply Migrations to the Database¶
After generating the script, apply the SQL changes to the database:
flask db upgrade
This updates the database schema (e.g., adding the new age field to the User table).
Practical Demo: Migration Flow from 0 to 1¶
Suppose you need to complete the following requirements step by step:
Phase 1: Create the User Table for the First Time¶
- Initialize Migration Environment: Run
flask db initto generate themigrationsfolder. - Generate Initial Migration Script: Modify the
Usermodel and run:
flask db migrate -m "create User table"
A script in migrations/versions will be created with SQL to create the User table.
3. Apply Migration: Run flask db upgrade to create the table in the database.
Phase 2: Modify the Model (Add a New Field)¶
If you need to add an age field to the User table:
1. Update the Model: Modify the User class in app.py:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
age = db.Column(db.Integer) # New field added
- Generate New Migration Script: Run:
flask db migrate -m "add age field to User"
A new script in migrations/versions will be generated with SQL to add the age column.
3. Apply the New Migration: Run flask db upgrade to add the age field to the database table.
Reverting Migrations (Optional)¶
If a migration causes issues or needs rollback, use the downgrade command to undo the last migration:
flask db downgrade
Note: downgrade only works if the migration script explicitly defines rollback logic (automatically generated by Flask-Migrate).
Common Issues and Beginner Tips¶
-
“migrations” Folder Already Exists?
Ifflask db initthrows an error (e.g., “migrations already exists”), you likely ran initialization twice. Simply skipinitand proceed withmigrateandupgrade. -
Migration Script Conflicts?
If scripts conflict during collaboration or multiple changes, checkmigrations/versionsand manually merge SQL statements. For beginners, use version control to isolate changes. -
SQLite vs. MySQL/PostgreSQL?
This example uses SQLite (no extra setup). For MySQL/PostgreSQL, updateSQLALCHEMY_DATABASE_URI(e.g.,mysql+pymysql://user:pass@localhost/dbname); migration logic remains identical.
Summary¶
Flask-Migrate follows a simple cycle: Modify Model → Generate Script → Apply to Database. Remember these 3 steps for smooth operations:
- Modify the Model: Update fields or table structures in
db.Model. - Generate Script: Use
flask db migrate -m "Description"to create a migration file. - Apply Changes: Run
flask db upgradeto apply the changes to the database.
This approach avoids manual SQL writing, ensures data safety, and is essential for development workflows!