SQLAlchemy-Migrate serves as a migration framework for Python applications, enabling safe schema evolution with out data loss. It allows developers to manage database changes through versioned scripts that can be aplied or rolled back incrementally.
To begin, install the package in your project environment:
pip install SQLAlchemy-Migrate
Initialize the migration repository by specifying your database connection string:
migrate init postgresql://user:pass@localhost/myapp
Create a new migration script to reflect structural changes. For example, to introduce an email field in the users table:
migrate create -m "Add email column to users" users
This generates a file in the versions/ directory. Open it and define the transformation logic within the upgrade() and downgrade() functions. To add the column:
def upgrade():
op.add_column('users', sa.Column('email', sa.String(length=120), nullable=True))
def downgrade():
op.drop_column('users', 'email')
Apply the migration to the target database using:
migrate upgrade head
If needed, revert the last change with:
migrate downgrade -N 1
For testing purposes, verify behavior programmatically. A sample test ensures the schema update is effective and reversible:
def test_add_email_field():
db = MyDatabase()
# Apply migration
upgrade(db)
# Confirm column presence
result = db.execute("SELECT * FROM users WHERE id = 1")
row = result.fetchone()
assert 'email' in row._asdict()
# Roll back
downgrade(db)
# Verify removal
result = db.execute("SELECT * FROM users WHERE id = 1")
row = result.fetchone()
assert 'email' not in row._asdict()
In a real-world scenario—such as anhancing a user profile system in an e-commerce application—this tool streamlines updates like adding an address field. The migration script would look like:
def upgrade():
op.add_column('users', sa.Column('address', sa.String(length=255), nullable=True))
def downgrade():
op.drop_column('users', 'address')
After running migrate upgrade head, existing user records are preserved while the schema evolves. Should the need arise, the change can be cleanly undone via the downgrade path.