SQLAlchemy1.3升级1.4后Mapper对象无属性报错如何解决
SQLAlchemy 1.4 aliased 关系属性报错解决方案
问题根因
这个报错和你之前遇到的列属性访问问题同源,来自SQLAlchemy 1.4对aliased()方法的不兼容逻辑调整:
- 1.3版本中,给
aliased()传入关系属性时,会自动解析为关系对应的ORM模型类,返回ORM层的AliasedClass实例,可直接访问模型上定义的列、关系属性 - 1.4版本中,给
aliased()传入关系属性时,默认返回SQL核心层的表Alias对象,仅暴露.c访问器下的列属性,不包含ORM模型定义的关系属性。此时直接点关系属性会返回底层Mapper对象,把这个对象传入下一级aliased()调用时,就会触发AttributeError: 'Mapper' object has no attribute 'relationship_two'报错。
修复方案
方案1:最小改动兼容(推荐)
创建别名时给aliased()传入use_mapper=True参数,强制返回和1.3行为一致的ORM层AliasedClass实例,原有业务代码不需要做其他调整:
def query(self, patient_id): cls = self.__class__ # 增加use_mapper=True参数即可对齐1.3行为 checkin = aliased(cls.relationship_one, use_mapper=True) study = aliased(checkin.relationship_two, use_mapper=True) # 原有查询逻辑保持不变,列访问也不需要额外加.c return result
方案2:显式传入目标模型类(符合1.4官方推荐写法)
不依赖自动解析,先通过关系属性取到对应的目标模型类,再传入aliased()创建ORM层别名,逻辑更明确:
def query(self, patient_id): cls = self.__class__ # 取第一层关系对应的模型类 checkin_model = cls.relationship_one.property.mapper.class_ checkin = aliased(checkin_model) # 取第二层关系对应的模型类 study_model = checkin_model.relationship_two.property.mapper.class_ study = aliased(study_model) # 后续查询join、属性访问和1.3写法完全一致 return result
注:以上两种方式创建的都是ORM层别名,访问列属性时直接用
alias.my_column即可,不需要额外加.c;只有使用核心层表别名时才需要通过.c层级访问列。
内容的提问来源于stack exchange,提问作者asdrubalivan
相关产品推荐
相关产品推荐

