How set schema for migration to flask

61 Views Asked by At

To migrate models to database, I use Flask-Migrate

I want migrations to be performed in a different DB schema, but the problem is that Flask-Migrate does not look at other schemas before migration

Here is my code

# app/__init__.py

app = Flask(__name__)
app.config.from_object(os.environ.get('FLASK_ENV'))
db = SQLAlchemy(app)
migrate = Migrate(app, db)

from app import models
# app/models.py

class Bot(db.Model):
    __tablename__ = "bot"
    __table_args__ = {"schema": "schema_tg_bot"}
    id = db.Column(db.Integer, primary_key=True)
    token = db.Column(db.String(), unique=True, nullable=False)
    name = db.Column(db.String(), nullable=False)

After execution commands

flask db migrate -m "init"

flask db upgrade

Created version in folder migrations

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('tg_bot',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('token', sa.String(), nullable=False),
    sa.Column('name ', sa.String(), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('token'),
    schema='schema_tg_bot'
    )
    # ### end Alembic commands ###

After adding new column

class Bot(db.Model):
    ...
    type = db.Column(db.String(), nullable=False)

it creates same file again

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('tg_bot',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('token', sa.String(), nullable=False),
    sa.Column('name', sa.String(), nullable=False),
    sa.Column('type', sa.String(), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('token'),
    schema='schema_tg_bot'
    )
    # ### end Alembic commands ###

But when calling flask db upgrade an error occurs

sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateTable) relation "tg_bot" already exists
        shop_id INTEGER NOT NULL,
        type VARCHAR NOT NULL,
        PRIMARY KEY (id),
        UNIQUE (shop_id),
        UNIQUE (token)
)

If you do not specify scheme, then everything will work fine

Created version in folder migrations

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('tg_bot', schema=None) as batch_op:
        batch_op.add_column(sa.Column('type', sa.String(), nullable=False))

    # ### end Alembic commands ###
1

There are 1 best solutions below

0
On

I searched the library and found the argument include_schemas

# app/__init__.py

app = Flask(__name__)
app.config.from_object(os.environ.get('FLASK_ENV'))
db = SQLAlchemy(app)
migrate = Migrate(app, db, include_schemas=True)

from app import models

It helped me, now version in folder migrations like this:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('tg_bot', schema='schema_tg_bot') as batch_op:
    batch_op.add_column(sa.Column('type', sa.String(), nullable=False))
    
    # ### end Alembic commands ###

But now I have a question, how do I choose only 1 scheme that flask can work with?