使用带鉴别器的泛型关联时父模型公共多态参数如何映射?
问题根因
你遇到的报错是因为Submit基类本身没有定义resource关系:这个反向引用是每个动态生成的Submit子类(比如BenchmarkSubmitReport)通过关系的backref绑定到各自对应的资源类(比如Benchmark)上的,基类的upload_datetime是依赖resource的关联代理,查询时SQLAlchemy在基类的映射里找不到resource属性就会抛出InvalidRequestError。
解决方案
方案一:修改查询语句(无需改动现有模型定义)
你之前尝试with_polymorphic没生效是因为没有加载所有子类的属性同时关联对应的resource表,调整查询写法即可:
from sqlalchemy.orm import with_polymorphic # 预加载所有Submit的多态子类,让SQLAlchemy识别到子类上的resource属性 all_submit_types = with_polymorphic(Submit, "*") query2 = db.session.query(all_submit_types)\ .join(all_submit_types.resource)\ .filter(all_submit_types.resource.upload_datetime < date)
方案二:用混合属性替代关联代理(支持直接用Submit.upload_datetime过滤)
如果希望保留Submit.query.filter(Submit.upload_datetime < date)这种简洁写法,可以把基类的关联代理替换为混合属性,自定义查询时的SQL表达式:
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy import case class Submit(db.Model): id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) resource_type = Column(String, nullable=False) # 删掉原来的upload_datetime关联代理,替换为下面的混合属性 __mapper_args__ = { 'polymorphic_on': resource_type, } # 实例层面调用逻辑不变,还是返回关联资源的上传时间 @hybrid_property def upload_datetime(self): return self.resource.upload_datetime # 查询层面的SQL表达式逻辑 @upload_datetime.expression def upload_datetime(cls): when_clauses = [] # 遍历所有继承了CreatesSubmit的资源类,拼接case条件 for resource_cls in CreatesSubmit.__subclasses__(): submit_subtype = resource_cls._submit_report_class when_clauses.append( (cls.resource_type == submit_subtype.__mapper_args__['polymorphic_identity'], resource_cls.upload_datetime) ) # 根据资源类型匹配对应资源表的上传时间字段 return case(*when_clauses, else_=None)
修改完成后你原来的query2写法就可以直接运行了,需要注意所有继承CreatesSubmit的类需要在查询执行前完成定义,否则遍历子类时会遗漏。
内容的提问来源于stack exchange,提问作者BorjaEst
相关产品推荐
相关产品推荐

