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
相关产品推荐
相关产品推荐

