我一直试图写一些混合属性的表达式,但我发现它们非常有限,我想知道我是否可以绕过这些限制。在
基本上,我发现它们要么与session.query(Model.hybrid_property)
或{
这是我的意思的一个例子,假设有两行叫做value1
和value2
,而{hybrid_property
。在
# With as_scalar()
>>> session.query(Model).filter(Model.value=='value1').all()
[([<__main__.Model object],)] # this is wanted
>>> session.query(Model.value).all()
[(u'value1',)]
# Without as scalar()
>>> session.query(Model).filter(Model.value=='value1').all()
[]
>>> session.query(Model.value).all()
[(u'value1',), (u'value2',)] # this is wanted
取决于是否使用as_scalar()
,它会改变它的工作方式。有没有一种方法可以同时使用这两种方法?在
下面是一些示例代码(经过编辑以显示完全不起作用的示例):
^{pr2}$其结果是:
[u'value1', u'value2']
[(u'value1',), (u'value2',)]
[]
[u'value1', u'value2']
[(u'value1',)]
[<__main__.Model object at 0x041D5C90>]
您看到的变化是由于表达式返回的对象类型和表达式的使用位置造成的。在
没有
as_scalar()
:表达式返回一个
Select
对象。在在
session.query(Model.value).all()
中,您的表达式被传递给session.query()
,而the docs可以接受:。。。所以没关系。我们可以用这个简单的问题证明:
在第二个查询
^{pr2}$session.query(Model).filter(Model.value == "value1").all()
中,您现在使用的是等式比较左侧的Select,然后该比较的结果被传递给query.filter()
。SQLAlchemy使用丰富的比较来比较列(like)元素,方法是在Column
上重载__eq__()
方法,您可以自己看到:但表达式返回一个
Select
对象:既然我们知道
Select.__eq__()
方法还没有重载,那么Select
对象和字符串之间的==
比较会产生什么结果呢?{cd13>总是^。当我们将False
作为查询的唯一筛选器时会发生什么情况?公司名称:WHERE 0 = 1
始终计算为false,因此查询始终为空。在使用
as_scalar()
:从the docs到
Select.as_scalar()
:因此,在这个scanario中,表达式返回一个
ScalarSelect
对象,它可以像列一样对待。在首先,解决
.filter(Model.value_scalar=='value1')
查询行为之间的差异:ScalarSelect的
__eq__()
实现与Column
相同,这意味着在Query.filter()
的上下文中,相等性测试会产生一些有意义的东西:因此,在这种情况下,查询会产生合理的结果。在
但是,在
session.query(Model.value_scalar).all()
的情况下,它只返回一个值,即使表中有两行。在此查询生成的sql是:
当
^{8}$ScalarSelect
被解释为一个列时,它本身是被选中的,而不是被选中的,就像在noas_scalar()
的情况下一样。为什么SELECT (SELECT...) AS anon_1
只从查询中返回一行,但我可以向您展示它发生在数据库级别,它不是sqlalchemy处理结果,而且出于某种原因只返回一个结果。这将通过原始dbapi连接执行相同的查询:因此,当表达式返回一个
Column
时,您将获得最一致的行为。在文档中有一个关于Join Dependent Hybrid Relationships的部分,其中它只使用相关的对象列作为表达式值,但您需要在查询中提供联接。在
如果模型是:
此查询:
session.query(Model.value).all()
呈现为…并按预期返回
[('value1',), ('value2',)]
。在但是这个查询:
session.query(Model).filter(Model.value == "value1").all()
呈现为:…但是返回两行,即使我们已经过滤了值:
[<__main__.Model object at 0x000002060369FEC8>, <__main__.Model object at 0x000002060348B108>]
。在在这部分文档中,他们处理的模型称为},他们说:
User
和{因此,如果我们进行查询
^{12}$session.query(Model).join(ModelRelation).filter(Model.value == "value1").all()
,则呈现的查询将变成:…并返回正确的1结果:
[<__main__.Model object at 0x000001606F030D48>]
。在文档接着描述了另一个例子Correlated Subquery Relationship Hybrid,但是我发现当
select()
是查询的目标实体时,它具有与上面完全相同的限制,因为它只返回单个结果。在相关问题 更多 >
编程相关推荐