SQLAlchemy 列属性和关系返回布尔值

Mat*_*ian 2 python sqlalchemy python-3.x

考虑两个数据模型:

Child(id, parent_id) :: ForeignKey on Child.parent_id => Parent.id
Parent(id, children) :: children = relationship(Child.parent_id == id)
Run Code Online (Sandbox Code Playgroud)

以下 SQLAlchemy 查询:

session.query(Parent.children).limit(1).all()
Run Code Online (Sandbox Code Playgroud)

产量:

[[False]]
Run Code Online (Sandbox Code Playgroud)

结果不正确,因为没有为行的每个返回列执行关系查询。我期待输出类似于以下内容:

[[{id:5, parent_id:8}]]
Run Code Online (Sandbox Code Playgroud)

注意当我通过获取整个父对象时。get,children属性查询就这样正确执行了

session.query(Parent).get(8)

# output
# { id: 8, children: [{id:5, parent_id:8}] }
Run Code Online (Sandbox Code Playgroud)

Red*_*ron 5

查看生成的 SQL,我们看到

>>> print str(s.query(Parent.children))
SELECT parent.id = child.parent_id AS children 
FROM parent, child
Run Code Online (Sandbox Code Playgroud)

由于您设置了限制并且我们有笛卡尔连接,因此您的第一个结果是 False (因为对于第一个父级和子级,parent.id 可能不等于 child.parent_id)。

AFAIK 的原因是它Parent.children不是传统的列,而是关系属性,因此行为不同。

假设您想获取与父项对应的所有子元素,您可以按照问题的第二部分所示进行操作

>>> par=session.query(Parent).filter_by(id=someid).first()
>>> par.children
Run Code Online (Sandbox Code Playgroud)

这里par.children将根据您的关系配置进行评估(请参阅手册中的关系加载技术),因此可能仅针对第二个表达式发出“加入”SQL(如果您有延迟加载关系)

另一种选择是明确加入并只获取孩子

>>> s.query(Parent).join(Parent.children).with_entities(Child).filter(Parent.id==1).all()
[<__main__.Child object at 0x145b950>, <__main__.Child object at 0x145ba50>]
Run Code Online (Sandbox Code Playgroud)