如何修改Python Enum实现namedtuple属性访问且兼容SQLAlchemy?
SQLAlchemy Enum 自定义属性访问与数据库值兼容解决方案
问题根源
你定义的ServerHealth Enum成员是HealthStatus namedtuple实例,但重写value方法返回self.name后,直接访问成员的low_bound等属性会触发AttributeError——这是因为Enum实例会把原始的namedtuple值存在__value__属性里,而Python默认不会自动将属性访问转发到这个内部值上。
解决方法
重写Enum类的__getattr__方法,把不存在的属性访问转发到内部的__value__对象(即对应的HealthStatus实例)上,同时保留自定义的value方法满足数据库存储需求。
修改后的完整代码
from enum import Enum, DynamicClassAttribute from collections import namedtuple from sqlalchemy import Column, Integer, Enum as SQLAlchemyEnum from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class ServerHealth(Enum): """Status of Server health.""" HealthStatus = namedtuple("HealthStatus", ["name", "low_bound", "high_bound"]) High = HealthStatus(name="High", low_bound=5, high_bound=24) Fair = HealthStatus(name="Fair", low_bound=3, high_bound=5) Low = HealthStatus(name="Low", low_bound=0, high_bound=3) @DynamicClassAttribute def value(self): return self.name def __getattr__(self, name): # 将属性访问转发到内部的HealthStatus实例 return getattr(self.__value__, name) # SQLAlchemy模型示例 class Server(Base): __tablename__ = "servers" id = Column(Integer, primary_key=True) server_health = Column(SQLAlchemyEnum(ServerHealth), nullable=True)
验证效果
ServerHealth.High.value返回"High",符合数据库存储要求ServerHealth.High.low_bound返回5,ServerHealth.High.high_bound返回24,属性访问正常- SQLAlchemy的数据库初始化、读写操作不受影响,因为存储到数据库的依然是
name字段的字符串值
内容的提问来源于stack exchange,提问作者Akash Kumar
相关产品推荐
相关产品推荐

