Python 动态检查过滤器以在SqlAlchemy上生成联接

Python 动态检查过滤器以在SqlAlchemy上生成联接,python,sqlalchemy,Python,Sqlalchemy,我有两个表,Foo和Bar,通过1-n关系链接(1Foo链接到nBar)。使用SqlAlchemy,我想使用客户端提供的通用过滤器查询一些Foo: def get_foos(foo_fltr): return session.query(Foo).filter(foo_fltr).all() foos = get_foos(foo_fltr=(Foo.value == 42)) 到目前为止还不错。现在,我还希望允许调用方在工具栏上进行筛选,例如: def get_foos(fooba

我有两个表,
Foo
Bar
,通过1-n关系链接(1
Foo
链接到n
Bar
)。使用SqlAlchemy,我想使用客户端提供的通用过滤器查询一些
Foo

def get_foos(foo_fltr):
    return session.query(Foo).filter(foo_fltr).all()

foos = get_foos(foo_fltr=(Foo.value == 42))
到目前为止还不错。现在,我还希望允许调用方在工具栏上进行筛选,例如:

def get_foos(foobar_fltr):
    return session.query(Foo).join(Bar).filter(foobar_fltr).all()

foos2 = get_foos(foobar_fltr=((Foo.value == 42) & (Bar.value == 13)))
def get_foos(fltr):
    q = session.query(Foo)
    if filter_reference_class(fltr, Bar):
        q = q.join(Bar)
    return q.filter(fltr).all()

foos1 = get_foo(fltr=(Foo.value == 42)) # No join
foos2 = get_foo(fltr=(Foo.value == 42) & (Bar.value == 13)) # Join
问题是,在
栏上进行过滤时,需要向查询中添加
连接(栏)
,因此需要两个方法或两个参数,这对实现和使用都很麻烦

我想做的是动态检查提供的SQLAlchemy筛选器,查看它是否与
条相关,如果是,则自动添加联接,例如:

def get_foos(foobar_fltr):
    return session.query(Foo).join(Bar).filter(foobar_fltr).all()

foos2 = get_foos(foobar_fltr=((Foo.value == 42) & (Bar.value == 13)))
def get_foos(fltr):
    q = session.query(Foo)
    if filter_reference_class(fltr, Bar):
        q = q.join(Bar)
    return q.filter(fltr).all()

foos1 = get_foo(fltr=(Foo.value == 42)) # No join
foos2 = get_foo(fltr=(Foo.value == 42) & (Bar.value == 13)) # Join
这样,只需要一个方法/一个参数。如果需要,将自动添加联接

我正在使用
sqlalchemy.sql.expression.ClauseeElement::get_children()
方法使用以下代码扫描子句树:

def inspect(fltr):
    for child in fltr.get_children():
        inspect(child)
    # How to test fltr here?

树的叶子是
AnnotatedColumn
对象。但是这里我被卡住了:如何检测列对象引用到哪个类?我在SqlAlchemy文档中看不到任何可以这样做的内容。

您似乎可以在
child.\u annotations[“parentmapper”]
,因此声明类是
child.\u annotations[“parentmapper”].class.


一种不那么脆弱的方法可能是直接在列的表(
child.table
)上联接,这也同样有效。

感谢您避免使用悬而未决的介词。您至少能给出一些具体的解决方案吗?这个问题有些道理,因为我们不想为不同的联接和筛选器编写更多的函数。@Roel不确定为什么您认为这不是一个具体的解决方案。问题是,“如何检测哪个类引用了列对象?”,答案是,使用
child.table
。哇!我的错!