我正在查询(通过sqllchemy(my_table对一列的条件,然后在另一列中检索不同的值。很简单
selection_1 = session.query(func.distinct(my_table.col2)).
filter(my_table.col1 == value1)
我需要反复执行此操作才能从my_table的不同列中获取不同的值。
selection_2 = session.query(func.distinct(my_table.col3)).
filter(my_table.col1 == value1).
filter(my_table.col2 == value2)
selection_3 = session.query(func.distinct(my_table.col4)).
filter(my_table.col1 == value1).
filter(my_table.col2 == value2).
filter(my_table.col3 == value3)
上面的代码有效,但由于我需要连续调用 6 次,它有点失控。我创建了一个类来处理方法链接:
class QueryProcessor:
def add_filter(self, my_table_col, value):
filter(my_table_col == value)
return self
def set_distinct_col(self, my_other_table_col):
self.my_other_table_col = my_other_table_col
return session.query(func.distinct(self.my_other_table_col))
理想情况下,我将能够像
selection_1 = QueryProcessor().set_distinct_col(my_table.col2).add_filter(my_table.col1, value1)
selection_2 = selection_1.set_distinct_col(my_table.col3).add_filter(my_table.col2, value2)
selection_3 = selection_2.set_distinct_col(my_table.col4).add_filter(my_table.col3, value3)
但是当我跑步时
selection_1 = QueryProcessor().set_distinct_col(my_table.col2).add_filter(my_table.col1, value1)
我收到以下错误:
Traceback (most recent call last):
File " ... "
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-20-789b26eccbc5>", line 10, in <module>
selection_1 = QueryProcessor().set_distinct_col(my_table.col2).add_filter(my_table.col1, value1)
AttributeError: 'Query' object has no attribute 'add_filter'
任何帮助将非常欢迎。
你真的不需要一个特殊的类。您现有的代码
selection_2 = session.query(func.distinct(my_table.col3)).
filter(my_table.col1 == value1).
filter(my_table.col2 == value2)
之所以有效,是因为filter
基于原始查询返回一个新查询,但添加了额外的过滤器。您可以循环访问列及其相应的值,将每个旧查询替换为其后续查询。
selection2 = session.query(func.distinct(my_table.col3))
for col, val in zip([my_table.col1, my_table.col2], [value1, value2]):
selection2 = selection2.filter(col == val)
selection_3 = session.query(func.distinct(my_table.col4))
for col, val in zip([mytable.col1, mytable.col2, mytable.col3],
[value1, value2, value3]):
selection_3 = selection_3.filter(col == val)
也就是说,代码的问题在于add_filter
实际上并没有调用查询的filter
方法,也不会更新包装的查询。
class QueryProcessor:
def set_distinct_col(self, my_other_table_col):
self.query = session.query(func.distinct(self.my_other_table_col))
return self
def add_filter(self, my_table_col, value):
self.query = self.query.filter(my_table_col == value)
return self
但是,这会带来一个问题:set_distinct_col
创建一个新查询,因此在以下内容中它实际上没有意义
selection_1 = QueryProcessor().set_distinct_col(my_table.col2).add_filter(my_table.col1, value1)
selection_2 = selection_1.set_distinct_col(my_table.col3).add_filter(my_table.col2, value2)
selection_3 = selection_2.set_distinct_col(my_table.col4).add_filter(my_table.col3, value3)
在现有实例上调用set_distinct_col
。它可以返回新查询或现有查询,但不能同时返回两者(至少,如果要进行链接,则不能(。
另请注意,selection_1
本身不是查询,而是selection_1.query
。
为了使add_filter()
函数按预期工作,您需要set_distinct_col()
函数返回对自身的引用(QueryProcessor
的实例(。session.query()
返回一个没有add_filter()
方法的Query
对象。 如果您执行类似Query.add_filter = add_filter
的操作,查询可以有一个add_filter
方法,但这是一种不好的做法,因为它会修改 Query 类,所以我不建议这样做。
你正在做的是一个更好的选择。为了能够访问使用set_distinct_col()
方法创建的查询,需要将其存储为实例变量。
下面,我通过将查询存储在实例变量中来完成此操作,query
self.query = session.query(func.distinct(self.my_other_table_col))
然后,我将add_filter()
方法更改为返回自身,以允许链接更多 add_filter(( 方法。
class QueryProcessor:
def add_filter(self, my_table_col, value):
self.query = self.query.filter(my_table_col == value)
return self
def set_distinct_col(self, my_other_table_col):
self.my_other_table_col = my_other_table_col
self.query = session.query(func.distinct(self.my_other_table_col))
return self
您还应该知道,一次可以使用多个筛选条件,因此实际上不需要将多个筛选器链接在一起。
session.query(db.users).filter(or_(db.users.name=='Ryan', db.users.country=='England'))
或
session.query(db.users).filter((db.users.name=='Ryan') | (db.users.country=='England'))
SQLAlchemy 中筛选器和filter_by之间的区别
附言此代码尚未经过测试