'How to wire up migrations in Flask with declarative base?

I'm using the declarative Base in flask_sqlalchemy. In my database.py file I have the following:

from sqlalchemy import create_engine
# from sqlalchemy.orm import scoped_session, sessionmaker
# from sqlalchemy.ext.declarative import declarative_base
# from flask_sqlalchemy import SQLAlchemy

# engine = create_engine("postgresql://postgres:@localhost/video_comparisons", convert_unicode=True)
# db_session = scoped_session(sessionmaker(autocommit=False,
#                                          autoflush=False,
#                                          bind=engine))
# Base = declarative_base()
# Base.query = db_session.query_property()

# Session = sessionmaker(bind = engine)

# db = SQLAlchemy()

# def init_db():
#     # import all modules here that might define models so that
#     # they will be registered properly on the metadata.  Otherwise
#     # you will have to import them first before calling init_db()
#     import yourapplication.models
#     Base.metadata.create_all(bind=engine)

Now, each of my models imports the Base object from database.py. This avoids circular imports.

Next, I'm trying to wire up the Flask migration module, which should work like this:

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

As you can see, I need to pass db into the Migrate constructor. But I don't have a db object, because I'm using the declarative Base, not creating it with db = SQLAlchemy(app).

What's the best way to do this? In the docs, I can't see how to connect the Migrate object to the database with this syntax.

Thanks, Louise



Solution 1:[1]

You have to import the db object from database.py :)

Solution 2:[2]

#timepass.py
from database import Base, metadata
from sqlalchemy import Table
class Timepass(Base):
    __table__ = Table('timepass', metadata, autoload=True)

#user.py
from project import db
class User(db.Model):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(15), unique=True)
    email = db.Column(db.String(50), unique=True)
    password = db.Column(db.String(80))

Solution 3:[3]

import os
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

URI = os.environ.get('SQLALCHEMY_DB_URI')

engine = create_engine(URI, echo=True)
Session = sessionmaker(bind=engine)

Base = declarative_base()

def get_engine():
    return engine

metadata=Base.metadata

for use, in factory method.

from flask_migrate import Migrate
import src.ext.database as db

migrate = Migrate()

def init_app(app):
    migrate.init_app(app, db)

in app.py your import init_app(app) This method, 100% Working...

BR :D

Solution 4:[4]

The key point is that you might not need Migrate along with declarative. Please refer to this page.

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db')
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    # import all modules here that might define models so that
    # they will be registered properly on the metadata.  Otherwise
    # you will have to import them first before calling init_db()
    import yourapplication.models
    Base.metadata.create_all(bind=engine)

The last two lines will help you to build tables if they do not exist. In my opinion, the Migrate library might be no more required.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Louise
Solution 2
Solution 3 Richard Guesso
Solution 4