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

时间:2016-02-11 16:32:58

标签: python sqlalchemy

我有两个表,FooBar,以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))

到目前为止一切顺利。现在我还想允许调用者过滤Bar,例如:

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)))

问题是,在Bar上进行过滤时,您需要向查询添加join(Bar),因此您需要两个方法或两个参数,这些方法实现和使用都很麻烦。

我想做的是动态检查提供的SQLAlchemy过滤器以查看它是否与Bar相关,如果是,自动添加连接,比如:

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.ClauseElement::get_children()方法使用以下代码扫描子树:

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

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

1 个答案:

答案 0 :(得分:-1)

您似乎可以在child._annotations["parentmapper"]获取父映射器,因此声明性类为child._annotations["parentmapper"].class_

一种不那么脆弱的方式可能就是直接加入到列(child.table)的表中,这应该也可以正常工作。