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

如何在SqlModel与Alembic中使用Enum类型实现迁移自动生成无需手动修改

SQLModel+Alembic自动生成枚举类型迁移的无手动修改方案

你遇到的报错本质是PostgreSQL中枚举属于自定义数据库类型,默认低版本Alembic生成迁移时仅生成新增字段语句,不会自动提前创建对应的枚举类型,导致执行加列语句时找不到对应类型。以下是三个可直接落地的解决方法:


方案1:配置Alembic钩子自动注入枚举创建语句

该方案无需修改现有模型代码,仅调整Alembic配置文件alembic/env.py,添加自动识别枚举列并注入创建语句的逻辑即可。

修改步骤:

  1. 在env.py头部导入依赖:
from alembic.operations import ops
from sqlalchemy.dialects.postgresql import ENUM as PGEnum
  1. 定义迁移指令处理钩子函数:
def auto_create_enums(context, revision, directives):
    script = directives[0]
    # 处理升级逻辑
    for idx, op in enumerate(script.upgrade_ops.ops):
        if isinstance(op, ops.AddColumnOp) and isinstance(op.column.type, PGEnum):
            enum_type = op.column.type
            # 生成带防重复创建判断的枚举创建语句
            create_sql = f"CREATE TYPE IF NOT EXISTS {enum_type.name} AS ENUM {tuple(enum_type.enums)};"
            # 将创建枚举语句插入到加列语句之前
            script.upgrade_ops.ops.insert(idx, ops.Execute(create_sql))
    # 可选:降级时自动删除枚举,根据自身需求决定是否开启
    # for idx, op in enumerate(script.downgrade_ops.ops):
    #     if isinstance(op, ops.DropColumnOp) and isinstance(op.column.type, PGEnum):
    #         enum_type = op.column.type
    #         drop_sql = f"DROP TYPE IF EXISTS {enum_type.name};"
    #         script.downgrade_ops.ops.append(ops.Execute(drop_sql))
  1. 找到run_migrations_online函数中的context.configure配置段,新增钩子函数参数:
context.configure(
    # 原有其他配置保持不变
    process_revision_directives=auto_create_enums,
)

配置完成后,后续新增枚举字段时Alembic自动生成的迁移文件就会自动包含创建枚举类型的语句,无需手动修改。


方案2:改用字符串存储+应用层枚举校验

如果不想修改Alembic配置,也可以调整模型实现,把枚举值存为普通字符串,用Pydantic校验保证合法性,彻底规避数据库自定义类型的迁移问题:

import enum
from typing import Optional
from pydantic import validator
from sqlmodel import SQLModel, Field

class SongType(enum.Enum):
    Rock = "Rock"
    Ballad = "Ballad"

class SongBase(SQLModel):
    name: str
    artist: str
    label: str = Field(index=False)
    song_type: Optional[str] = None
    year: Optional[int] = None

    @validator("song_type")
    def check_song_type(cls, value: Optional[str]) -> Optional[str]:
        if value is None:
            return value
        allowed_values = [item.value for item in SongType]
        if value not in allowed_values:
            raise ValueError(f"song_type仅允许为{allowed_values}中的值")
        return value

class Song(SongBase, table=True):
    id: int = Field(default=None, primary_key=True, nullable=False)

这种方式Alembic生成的迁移就是普通的VARCHAR类型新增语句,完全不需要手动调整,且兼容所有数据库类型,无需担心跨库适配问题。


方案3:升级依赖版本

你当前使用的依赖版本较低,新版Alembic(>=1.10.0)和SQLModel(>=0.0.8)已经原生支持枚举类型的自动迁移生成,直接升级对应依赖即可解决问题,不需要额外配置:

pip install alembic>=1.10.0 sqlmodel>=0.0.8

升级后重新生成迁移文件,就会自动包含枚举创建的相关逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:24:07