Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve existing tables in database when running Flask-Migrate

I have a database with existing tables. My code has a User model. I generated a revision using Flask-Migrate and ran it, and it deleted my existing tables while creating the user table. How can I run migrations without removing the existing tables?

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'my_data'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('db', MigrateCommand)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))

if __name__ == '__main__':
    manager.run()
like image 764
Иван Семенов Avatar asked Aug 20 '16 18:08

Иван Семенов


2 Answers

If you have existing tables in your database, and they don't have a corresponding model in your code, Alembic (Flask-Migrate) only knows that there is a difference between your database and your code. It can't know (by default) that you meant to leave those tables untouched.

Pass an include_object function to the environment to effect what database objects Alembic will generate commands for. The following example skips the listed table names, but allows everything else.

def include_object(object, name, type_, reflected, compare_to):
    if type_ == 'table' and name in ('table', 'names', 'to', 'skip'):
        return False

    return True

# in env.py
context.configure(
    # ...
    include_object=include_object
)
like image 152
davidism Avatar answered Sep 23 '22 00:09

davidism


There is yet another solution for this problem, it goes like this:

Alembic looks for the tables in target_metadata argument, which accepts also list of objects, therefore we can pass there models from celery.

All we need to do is change:

file - env.py
from

target_metadata = current_app.extensions["migrate"].db.metadata

to

from celery_sqlalchemy_scheduler.models import ModelBase

...

target_metadata = [current_app.extensions["migrate"].db.metadata, ModelBase.metadata]
like image 32
Bartek Avatar answered Sep 27 '22 00:09

Bartek