SQLAlchemy关联查询问题:如何通过GrandParent.id与Child.index查询Child
解决SQLAlchemy跨关联查询的AttributeError问题
先把你的模型结构贴出来方便参考:
class GrandParent(Base): __tablename__ = "grandparent" id = Column(Integer, primary_key=True) name = Column(String(16)) # One-to-one relationship parent_id = Column(Integer, ForeignKey('parent.id')) parent = relationship("Parent", backref=backref("grandparent", uselist=False)) def __init__(self, name): self.name = name class Parent(Base): __tablename__ = "parent" id = Column(Integer, primary_key=True) name = Column(String(16)) # One-to-many relationship children = relationship("Child", backref="parent") def __init__(self, name): self.name = name class Child(Base): __tablename__ = "child" id = Column(Integer, primary_key=True) name = Column(String(16)) index = Column(Integer) parent_id = Column(Integer, ForeignKey('parent.id')) def __init__(self, name, idx): self.name = name self.index = idx def __repr__(self): return self.name
你尝试用链式属性查询时遇到了这个报错:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Child.parent has an attribute 'grandparent'
为啥实例能访问但查询不行?
其实很好理解:当你操作已经加载到内存的实例对象时(比如你示例里的foo),SQLAlchemy已经帮你把关联对象都加载好了,所以能链式访问foo.parent.grandparent.id;但构造查询语句时,你是在和SQLAlchemy的查询API打交道,它需要明确知道要关联哪些表,不能直接像访问实例属性那样链式调用关联关系。
另外还要注意:Python的and不能直接用在SQLAlchemy的filter里,得用&(还要加括号,因为运算符优先级问题),或者拆分多个filter调用。
正确的查询方法
给你两种常用的可行写法:
方法1:显式JOIN关联表
这种方式最清晰,明确告诉SQLAlchemy要关联的表:
c = session.query(Child)\ .join(Parent)\ .join(GrandParent)\ .filter(GrandParent.id == 2, Child.index == 3)\ .first()
方法2:使用has()方法(适合简单关联场景)
对于一对一/一对多的关联,也可以用关系属性的has()方法来简化查询:
c = session.query(Child)\ .filter( Child.parent.has(GrandParent.id == 2), Child.index == 3 )\ .first()
额外注意点
如果用&组合条件,一定要加括号,比如:
c = session.query(Child)\ .join(Parent)\ .join(GrandParent)\ .filter( (GrandParent.id == 2) & (Child.index == 3) )\ .first()
因为&的优先级比==高,不加括号会导致逻辑错误。
这样就能正确查到你想要的Child对象啦!
内容的提问来源于stack exchange,提问作者GuillaumeA
相关产品推荐
相关产品推荐

