Alembic - 反向工作流程升级/降级

问题描述 投票:0回答:1

我在 Alembic + FastAPI + PostgreSQL 上遇到这个问题

SQL Alchemy Alembic 反向生成迁移,降级创建表并升级删除表,而数据库为空。

例如:

alembic revision --autogenerate -m "Testing 2"
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_Site_keyword' on 'Site'
INFO  [alembic.autogenerate.compare] Detected removed table 'Site'
  Generating /app/migrations/versions/1e3a0f40182c_testing_2.py ...  done

我检查了文件,得到了这个:

"""Testing 2

Revision ID: 1e3a0f40182c
Revises: 928ab2a61fa7
Create Date: 2024-04-04 08:32:29.784316

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '1e3a0f40182c'
down_revision: Union[str, None] = '928ab2a61fa7'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index('ix_Site_keyword', table_name='Site')
    op.drop_table('Site')
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('Site',
    sa.Column('id', sa.UUID(), autoincrement=False, nullable=False),
    sa.Column('title', sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.Column('keyword', sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.Column('description', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('is_active', sa.BOOLEAN(), autoincrement=False, nullable=True),
    sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('updated_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('deleted_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.PrimaryKeyConstraint('id', name='Site_pkey')
    )
    op.create_index('ix_Site_keyword', 'Site', ['keyword'], unique=False)
    # ### end Alembic commands ###

为什么要做这个?如果我切换块(将升级块放入降级块,反之亦然)如果我运行下一个自动迁移,我会在升级功能中得到所有删除语法......所以,我总是必须重写代码。

这是怎么回事?

更新:这是我的 env.py 文件。

from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool
from database.orm import Base
from alembic import context


config = context.config

if config.config_file_name is not None:
    fileConfig(config.config_file_name)

target_metadata = Base.metadata



def run_migrations_offline() -> None:
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online() -> None:
    connectable = engine_from_config(
        config.get_section(config.config_ini_section, {}),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        with context.begin_transaction():
            context.run_migrations()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()
python postgresql fastapi alembic
1个回答
0
投票

最后:

env.py

from database.orm import Base
from models import site

models.site.py

from sqlalchemy import Boolean, Column, String, DateTime, Text

from database.orm import Base
import uuid
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy import func


def generate_uuid():
    return str(uuid.uuid4())

class Site(Base):
    __tablename__ = "Site"

    id = Column(UUID(as_uuid=True), primary_key=True, unique=True, default=generate_uuid)
    title = Column(String)
    keyword = Column(String, index=True)
    description = Column(Text)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=func.now)
    updated_at = Column(DateTime, default=func.now)
    deleted_at = Column(DateTime, default=func.now)

数据库.orm.py

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

SQLALCHEMY_DATABASE_URL = "postgresql://postgres:example@database/db_new"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

运行:

alembic revision --autogenerate -m "Tes4"
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'Site'
INFO  [alembic.autogenerate.compare] Detected added index ''ix_Site_keyword'' on '('keyword',)'
  Generating /app/migrations/versions/f3d6623e75ec_tes4.py ...  done

迁移.versions.f3d6623e75ec_tes4.py

"""Tes4

Revision ID: f3d6623e75ec
Revises: 
Create Date: 2024-04-04 15:19:09.018548

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'f3d6623e75ec'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('Site',
    sa.Column('id', sa.UUID(), nullable=False),
    sa.Column('title', sa.String(), nullable=True),
    sa.Column('keyword', sa.String(), nullable=True),
    sa.Column('description', sa.Text(), nullable=True),
    sa.Column('is_active', sa.Boolean(), nullable=True),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.Column('deleted_at', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('id')
    )
    op.create_index(op.f('ix_Site_keyword'), 'Site', ['keyword'], unique=False)
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_Site_keyword'), table_name='Site')
    op.drop_table('Site')
    # ### end Alembic commands ###
© www.soinside.com 2019 - 2024. All rights reserved.