我有两个表,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))
到目前为止一切顺利。现在我还想允许调用者过滤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文档中看不到任何内容。
答案 0 :(得分:-1)
您似乎可以在child._annotations["parentmapper"]
获取父映射器,因此声明性类为child._annotations["parentmapper"].class_
。
一种不那么脆弱的方式可能就是直接加入到列(child.table
)的表中,这应该也可以正常工作。