python - 如何在 sqlalchemy 混合表达式中运行查询?
问题描述
有一个与类标签有“多”关系的类 Run。我需要能够根据标签(tag_collection)的功能过滤运行。
下面是我的代码片段。在这种情况下,我使用的是自动映射器,但我认为这并不重要。
Base = automap_base()
class Run(Base):
__tablename__ = 'runs'
macro_id = Column(ForeignKey('macros.id'))
@hybrid_property
def tag_count(self):
return(len(self.tag_collection))
@hybrid_property
def default_region(self):
return(reduce(lambda memo, t: memo or t.name == "region" and t.value == "default", self.tag_collection, False))
@default_region.expression
def default_region(cls):
# how do I do the query here?
class Tag(Base):
__tablename__ = 'tags'
run_id = Column(ForeignKey('runs.id'))
如果我得到一个 Run 的实例,我可以使用该default_region
属性,但是当我运行一个查询并尝试使用该属性进行过滤时,我要么在装饰方法default_region
中获取传入的 Run 类(作为自身),要么我最终出现在装饰方法中,该方法也接收 Run 类。@hybird_property
default_region
@default_region.expression
default_region
示例查询:
session.query(Run).filter(Run.default_region == True).all()
我想我需要在@default_region.expression
装饰default_region
方法中进行查询,但我看不到如何获取会话句柄。我知道Session.object_session(someobject)
,但我认为someobject
需要是 orm 类的实例而不是类本身。
我认为我的过滤方法完全错误,或者我需要以某种方式在该@default_region.expression
装饰default_region
方法中获取会话对象的句柄。
有没有更好的方法来完成这种过滤?
如何在@default_region.expression
装饰default_region
方法中获取会话?
解决方案
这在我看来是Correlated Subquery Relationship Hybrid。当Run.default_region
被添加为过滤器时,您要更新要添加的查询
WHERE EXISTS (
SELECT 1 FROM tags
WHERE run_id = runs.id
AND name = "region"
AND value = "default")
exists()
使用函数将其作为表达式返回:
from sqlalchemy.sql import exists, and_
@default_region.expression
def default_region(cls):
return exists([1]).where(and_(
Tag.run_id == cls.id,
Tag.name == 'region',
Tag.value == 'default'))
注意这里要避免使用== True
or == False
,没必要!只需直接使用该属性:
session.query(Run).filter(Run.default_region).all()
或用于~
否定:
session.query(Run).filter(~Run.default_region).all()
通过定义属性的.expression
方法,您已经告诉 SQLAlchemy 在访问类上的属性时使用该方法,因此上下文始终是那里的类。如果没有定义.exists
(或 a .comparator
),Run.default_region
将调用default_region
getter(用 `@hybrid_property 装饰的方法)作为类方法,因此只有这样该方法才必须与传入的实例或类一起使用。对于某些混合属性实现,这恰好取决于它们如何在上下文中使用属性。
至于default_region
实例属性的实现,我不会reduce()
在那里使用;使用any()
功能:
@hybrid_property
def default_region(self):
return any(
t.name == "region" and t.value == "default"
for t in self.tag_collection)
any()
找到匹配项时停止迭代提供的生成器表达式。
推荐阅读
- proxy - 使用 NetworkManager nmcli 配置代理服务器
- java - 如何为上述查询转换休眠条件查询?
- swift - Swift 添加另一个类的子视图
- dax - 不同值的无效总和
- ms-access - Ms Access 2007 中的记录集问题
- javascript - jQuery 在代码中停止工作,但在控制台(WordPress)中工作
- css - 位置:粘性在 flexbox 子项中不起作用
- java - Spark Java API:加入两个数据集
- ios - 如何为标签添加样式以快速显示字符串
- jquery - 如何在angular1中包含来自node_modules的jquery