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

SQLAlchemy+PostgreSQL中IntEnum存储异常求助:如何存整数而非枚举名

解决SQLAlchemy中IntEnum枚举值以整数存入PostgreSQL的问题

SQLAlchemy默认的Enum类型映射到PostgreSQL时,会把枚举成员的名称(比如admin)存在数据库里,而非IntEnum对应的整数值。要实现整数存储,有两种实用方案:


方案一:改用Integer列+枚举属性转换

直接将数据库列定义为Integer,通过Python属性方法在代码层面处理枚举与整数的转换,既保证数据库存纯整数,又不影响代码中使用枚举成员操作。

修改后的完整代码:

import enum
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class UserRole(enum.IntEnum):
    reader: int = 7
    Pro_reader: int = 6
    publisher: int = 5
    editor: int = 4
    small_manager: int = 3
    big_manager: int = 2
    admin: int = 1

class User(Base):
    __tablename__ = "user"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, nullable=False, index=True)
    username = Column(String, unique=True, nullable=False, index=True)
    hashed_password = Column(String, nullable=False)
    # 数据库实际存储整数的列
    _user_role = Column("user_role", Integer, default=UserRole.reader.value)

    @property
    def user_role(self) -> UserRole:
        # 读取时转成枚举成员
        return UserRole(self._user_role)
    
    @user_role.setter
    def user_role(self, role: UserRole):
        # 赋值时转成整数存库
        self._user_role = role.value

使用示例:

# 赋值用枚举成员
new_user = User(user_role=UserRole.admin)
# 读取时直接拿到枚举对象
print(new_user.user_role)  # 输出 UserRole.admin
print(new_user.user_role.value)  # 输出 1

方案二:自定义TypeDecorator实现枚举值存储

如果想保持模型字段的枚举语义(写法更直观),可以自定义类型装饰器,让SQLAlchemy自动将枚举值存入数据库:

import enum
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.types import TypeDecorator

Base = declarative_base()

class IntEnumType(TypeDecorator):
    impl = Integer
    cache_ok = True

    def __init__(self, enum_type):
        super().__init__()
        self.enum_type = enum_type

    def process_bind_param(self, value, dialect):
        if value is None:
            return None
        # 绑定参数时转成枚举值
        return value.value

    def process_result_value(self, value, dialect):
        if value is None:
            return None
        # 查询结果转成枚举成员
        return self.enum_type(value)

class UserRole(enum.IntEnum):
    reader: int = 7
    Pro_reader: int = 6
    publisher: int = 5
    editor: int = 4
    small_manager: int = 3
    big_manager: int = 2
    admin: int = 1

class User(Base):
    __tablename__ = "user"

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True, nullable=False, index=True)
    username = Column(String, unique=True, nullable=False, index=True)
    hashed_password = Column(String, nullable=False)
    # 使用自定义类型映射枚举
    user_role = Column(IntEnumType(UserRole), default=UserRole.reader)

注意事项

如果之前已经创建过数据库表,必须修改表结构:

  • 直接删除原表后重建;
  • 用迁移工具(如Alembic)编写脚本,将原user_role列的枚举类型改为整数类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:26:04