"""手动迁移:建 site_nav_click(之前是 db.create_all() 建的,不在 alembic 里)。 现有 DB 已经有一张同名的表,迁移以空操作为主;对空 DB(首次部署 / 新容器)会建表。 """ from alembic import op import sqlalchemy as sa revision = 'a47a5d2a3f1b' down_revision = 'afa5cfb23a85' branch_labels = None depends_on = None def upgrade(): bind = op.get_bind() inspector = sa.inspect(bind) if 'site_nav_click' in inspector.get_table_names(): # 已存在的 DB:表在,但 alembic 视角下没版本记录 → 跳过 DDL # 同时保证 anon_id 列存在(方案 C 升级路径) cols = {c['name'] for c in inspector.get_columns('site_nav_click')} with op.batch_alter_table('site_nav_click') as batch: if 'anon_id' not in cols: batch.add_column(sa.Column('anon_id', sa.String(length=36), nullable=True, comment='匿名访客ID')) batch.create_index('ix_site_nav_click_anon_id', ['anon_id'], unique=False) return op.create_table( 'site_nav_click', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='记录ID'), sa.Column('nav_id', sa.Integer(), nullable=False, comment='被点击的导航ID'), sa.Column('anon_id', sa.String(length=36), nullable=True, comment='匿名访客ID'), sa.Column('day', sa.String(length=10), nullable=True, comment='日期 YYYY-MM-DD'), sa.Column('ip', sa.String(length=64), nullable=True, comment='访客IP'), sa.Column('clicked_at', sa.DateTime(), nullable=True, comment='点击时间'), sa.PrimaryKeyConstraint('id'), ) with op.batch_alter_table('site_nav_click') as batch: batch.create_index('ix_site_nav_click_nav_id', ['nav_id'], unique=False) batch.create_index('ix_site_nav_click_anon_id', ['anon_id'], unique=False) batch.create_index('ix_site_nav_click_day', ['day'], unique=False) batch.create_index('ix_site_nav_click_clicked_at', ['clicked_at'], unique=False) def downgrade(): op.drop_table('site_nav_click')