SQLAlchemy关联查询:如何仅获取子模型指定字段并保持对象结构
解决SQLAlchemy一对一关联按需加载字段的问题
假设你的模型定义大致如下(一对一关联):
from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.orm import relationship, declarative_base Base = declarative_base() class Objects(Base): __tablename__ = 'objects' id = Column(Integer, primary_key=True) # 其他Objects字段... device_id = Column(Integer, ForeignKey('devices.id'), unique=True) device = relationship("Devices", back_populates="object", uselist=False) class Devices(Base): __tablename__ = 'devices' id = Column(Integer, primary_key=True) state = Column(String) settings = Column(String) # 无需加载的冗余字段 object = relationship("Objects", back_populates="device", uselist=False)
有两种可行方案满足你的需求:
方案一:使用joinedload + load_only
通过关联加载指定仅获取Devices的state字段,同时保留Objects的全部字段,返回结果为Objects实例,可直接通过属性访问关联数据:
from sqlalchemy.orm import joinedload, load_only # 执行查询 results = session.query(Objects).options( joinedload(Objects.device).load_only(Devices.state) ).all() # 属性访问示例 for res in results: print(res.id) # 访问Objects的字段 print(res.device.state) # 访问Devices的state字段,冗余字段不会被加载
- 该方案默认生成左连接,即使
Objects未关联Devices也会被返回 - 未指定的
Devices字段(如settings)若被访问会触发懒加载,若需避免可在关系定义中添加lazy="raise"禁用
方案二:显式外连接 + contains_eager
通过显式外连接关联表,再用contains_eager将查询到的Devices数据绑定到Objects的关联属性,同时限制加载字段:
from sqlalchemy.orm import contains_eager, load_only # 执行查询(outerjoin确保无关联Devices的Objects也能被返回) results = session.query(Objects).outerjoin(Objects.device).options( contains_eager(Objects.device).load_only(Devices.state) ).all() # 属性访问方式与方案一完全一致 for res in results: print(res.id) print(res.device.state)
- 此方案通过显式连接控制SQL生成,更适合需要自定义连接条件的场景
- 返回的
Devices实例仅包含state字段,不会加载冗余数据
内容的提问来源于stack exchange,提问作者Кирилл Романенко
相关产品推荐
相关产品推荐

