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

无法为SQLAlchemy的MappedColumn添加自定义属性_editable,触发AttributeError

解决SQLAlchemy MappedColumn添加自定义属性的AttributeError问题

错误原因

SQLAlchemy的MappedColumn类通过__slots__机制限制了实例允许拥有的属性列表,类定义中没有预定义_editable属性,因此直接给实例赋值该属性会触发AttributeError。


解决方案一:利用原生info参数存储自定义属性(推荐)

SQLAlchemy的mapped_column支持info参数,专门用于存储自定义元数据,完全符合框架设计规范,兼容性拉满:

from typing import Any
from sqlalchemy.orm import mapped_column as mc
from sqlalchemy.orm.properties import MappedColumn
from sqlalchemy import Integer, String

def mapped_column(*args, editable=True, **kwargs) -> MappedColumn[Any]:
    # 把editable参数存入info字典,没有info则先初始化
    kwargs.setdefault('info', {})['editable'] = editable
    return mc(*args, **kwargs)

# 使用示例
class User(Base):
    __tablename__ = 'users'
    id = mapped_column(Integer, primary_key=True, editable=False)
    name = mapped_column(String(50))

# 访问自定义属性
print(User.__table__.c.name.info['editable'])  # 输出 True
print(User.__table__.c.id.info['editable'])    # 输出 False

解决方案二:子类化MappedColumn(无需复制全部构造函数)

如果你坚持要通过实例属性直接访问,不需要复制原构造函数全部内容,只需在子类中传递所有参数给父类即可:

from typing import Any
from sqlalchemy.orm import mapped_column as mc
from sqlalchemy.orm.properties import MappedColumn
from sqlalchemy import Integer, String

class EditableMappedColumn(MappedColumn):
    def __init__(self, *args, editable=True, **kwargs):
        super().__init__(*args, **kwargs)
        self._editable = editable

def mapped_column(*args, editable=True, **kwargs) -> EditableMappedColumn[Any]:
    return EditableMappedColumn(*args, editable=editable, **kwargs)

# 使用示例
class User(Base):
    __tablename__ = 'users'
    id = mapped_column(Integer, primary_key=True, editable=False)
    name = mapped_column(String(50))

# 访问自定义属性
print(User.id.property._editable)  # 输出 False
print(User.name.property._editable)# 输出 True

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 16:30:10