You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQLAlchemy中添加Enum字段?迁移时遇ProgrammingError

问题描述

我需要为User模型添加user_type字段,但执行alembic upgrade head时始终遇到sqlalchemy.exc.ProgrammingError错误。

models/user.py

class UserType(enum.Enum):
    USER = "USER"
    SELLER = "SELLER"
    ADMIN = "ADMIN"

class User(ModelBase):
    __tablename__ = "user"
    username = Column(String(64), nullable=False)
    email = Column(String(64), nullable=False)
    phone_number = Column(String(32), unique=True, nullable=False)
    password = Column(String(128))
    avatar = Column(JSONB, nullable=True)
    address = Column(String(128), nullable=True)
    user_type = Column(Enum(UserType, name="user_type"), default=UserType.USER)  # 新增字段

自动生成的alembic迁移文件

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('user', sa.Column('user_type', sa.Enum('USER', 'SELLER', 'ADMIN', name='user_type'), nullable=True))
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('user', 'user_type')
    # ### end Alembic commands ###

执行命令后报错:

sqlalchemy.exc.ProgrammingError: (sqlalchemy.dialects.postgresql.asyncpg.ProgrammingError) <class 'asyncpg.exceptions.UndefinedObjectError'>: type "user_type" does not exist
[SQL: ALTER TABLE "user" ADD COLUMN user_type user_type]

问题原因与解决方法

原因

PostgreSQL使用枚举类型时,必须先在数据库中创建枚举类型,才能在表字段中引用。自动生成的迁移文件直接尝试添加字段,但此时user_type枚举类型尚未创建,因此触发报错。

解决步骤

  1. 修改迁移文件的upgrade函数,先创建枚举类型,再添加字段:
def upgrade() -> None:
    # 先创建user_type枚举类型,checkfirst避免重复创建报错
    user_type_enum = sa.Enum('USER', 'SELLER', 'ADMIN', name='user_type')
    user_type_enum.create(op.get_bind(), checkfirst=True)
    # 添加字段,设置server_default让已有数据自动填充默认值
    op.add_column('user', sa.Column('user_type', user_type_enum, nullable=True, server_default='USER'))
  1. 修改downgrade函数,删除字段后清理枚举类型(更规范的回滚操作):
def downgrade() -> None:
    op.drop_column('user', 'user_type')
    # 删除枚举类型,checkfirst避免不存在时报错
    user_type_enum = sa.Enum('USER', 'SELLER', 'ADMIN', name='user_type')
    user_type_enum.drop(op.get_bind(), checkfirst=True)
  1. 重新执行alembic upgrade head即可完成迁移。

补充说明

  • 如果需要user_type字段非空,可在本次迁移完成后,再生成一次迁移将字段改为nullable=False,避免已有数据为空导致的报错。

内容的提问来源于stack exchange,提问作者haku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 12:23:17