Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Flask-migrate across multiple development environments

I have flask-migrate (version 1.8.0) working well with a sqlite database in a development environment. Now I would like to migrate our data to MySQL and maintain all of our migration history (so it stays in sync with our Flask-SQLAlchemy models in our git repository).

I created an empty MySQL database, and after changing my SQLALCHEMY_DATABASE_URI, I tried running:

python manage.py db upgrade

That resulted in an error about not being able to drop the table migrate_version. (Which makes sense, since this is a new database, although sqlite actually contains the table 'alembic_version' not 'migrate_version'.)

So, I tried to initialize this new database:

python manage.py db init

Now I get an error: "Directory migrations already exists".

I can rename that folder and re-run the command with no problem, but then I lose all of my previous migrations. I think we would have the same issues when we also transition to our test and production environments.

I've seen in the docs Flask-Migrate has multiple database support, but I think that looks to be more for maintaining multiple databases in a single development environment. Is there a way to have Flask-Migrate track changes across multiple development environments?

like image 882
AmZar Avatar asked Feb 07 '23 10:02

AmZar


2 Answers

To address the real issue in the OP's question, you need to use the --directory flag to initiate a migrations directory specific to your each environment's database.

From the flask-migrate documentation:

All commands also take a --directory DIRECTORY option that points to the directory containing the migration scripts. If this argument is omitted the directory used is migrations.

So:

flask db init --directory=[DIRECTORY NAME]

Flask-Migrate itself has no memory of your database, so when running migration commands with flask db, it will reference the specified migrations directory (by default, when the --directory flag is not used, this is called 'migrations').

flask db migrate --directory=[DIRECTORY_NAME]

etc.

It goes without saying that the flask command will reference the application context as configured by your config file or environment variables.

I typically create a migration directory for each environment with an explicit reference to the environment: e.g. development and staging, with something like 'migrations_dev' and 'migrations_stg'.

Hope this is helpful.

like image 147
pemm Avatar answered Feb 12 '23 10:02

pemm


Here are the steps I took to transition from SQLite to MySQL and maintain all the migration history. I highly suspect there is a better way to do this, but it worked for me.

Initialize the new, blank database using another folder for your "new" migrations

python manage.py db init -d tmp

Create a migration

python manage.py db migrate -d tmp -m "Bring MySQL up to date"

Apply the migration

python maange.py db upgrade -d tmp

Now, you can delete the "tmp" migrations folder. You no longer need it. Find the HEAD migration. Look for 'Rev: your_revision_num (head)'

python manage.py db show 

Run an update statement against your MySQL database

update alembic_version set version_num = 'your_revision_num'

Now your MySQL database schema should match your old SQLite schema and you'll have your full migration history as well.

like image 24
AmZar Avatar answered Feb 12 '23 11:02

AmZar