SQLAlchemy 多对一连接
我在使用 SQLAlchemy
的时候,有两个 SQL
表之间是多对一的关系。举个例子:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
child_id = Column(Integer, ForeignKey('child.id'))
child = relationship("Child")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String(100))
我想做的是把 Child
类的信息添加到父类中。我尝试了一下 join
查询:
result = session.query(Parent).join(Child).all()
虽然这个查询把合适的 Child
对象添加到了 Parent
对象的 parent.child
里,但它只返回了每个孩子对应的第一个父亲。也就是说,我的数据库里有四个父亲和两个孩子,而这个查询只返回了父亲 1 和 3。我该怎么修改这个查询才能返回所有四个父亲呢?另外,如果我只想把孩子的名字添加到父亲里,而不是整个孩子对象,像 parent.child_name
这样,我该怎么做呢?
1 个回答
1
如何在连接子项时获取所有父项
问题在于,有些父项没有子项,所以用普通的连接方式会把这些父项排除掉。你应该使用外连接,这样就能把所有父项都包括进来。此外,单纯地添加连接并不会自动加载子项。你需要指定 contains_eager
或 joinedload
来确保在加载父项时也能把子项一起加载出来。
# use contains_eager when you are joining and filtering on the relationship already
session.query(Parent).join(Parent.child).filter(Child.name == 'Max').options(contains_eager(Parent.child))
# use joinedload when you do not need to join and filter, but still want to load the relationship
session.query(Parent).options(joinedload(Parent.child))
如何将 child_name 添加到父项
你需要使用一个叫做 关联代理 的东西。
from sqlalchemy.ext.associationproxy import association_proxy
class Parent(Base):
child = relationship('Child')
child_name = association_proxy('child', 'name')
# you can filter queries with proxies:
session.query(Parent).filter(Parent.child_name == 'Min')
使用关联代理可以做一些很酷的事情,记得去看看文档了解更多信息。