【发布时间】:2019-07-24 16:01:36
【问题描述】:
我有一个数据库,我需要返回与查询匹配或看起来相似的任何值。
使用 flask-sqlalchemy 我可以手动过滤,但我无法使用列表推导或任何其他 Python 方法获取对象列表。
我已经尝试创建一个包含所有模型列(我有一个列表)的字典,并将搜索值传递给 filter_by 查询
column_dict_and_value = {column_name:'value' for column_name in columns}
a = model.query.filter_by(**column_dict_and_value).all()
...但甚至不返回现有对象,尽管
a = model.query.filter_by(column_name='value').all()
实际返回对象。
我尝试了filter(.like('%')),它有点工作
a = model.query.filter(model.column_name.like('valu%')).all()
返回与该模式匹配但针对该列的所有对象的列表,我想遍历所有列。基本上是一个完整的搜索,因为我不确定用户要查找什么,如果查询存在于任何列上,我想显示对象,如果查询不完整,我想显示对象列表,例如任何搜索中的 * .
我尝试使用列表推导来遍历模型属性,但显然我不允许这样做:
a = [model.query.filter(model.column.like('valu%')) for column in columns]
...这抱怨 column 不是模型的属性,由于语法,这是有道理的,但无论如何我不得不尝试,innit?
我是数据库和类对象方面的新手,所以请保持温和。我试图寻找类似的答案,但找不到适合我的答案。 filter_by(one_column, second_column, etc) 在我看来并不像 pythonic,如果出于任何原因我更改模型,我也需要更改查询,因为在我看来创建模型的 dict 理解更万无一失。
解决方案
根据calestini 提出的答案,我编写了这个似乎可以解决问题的代码。它还会清理列表,因为如果 all() 没有任何结果(因为它会查看每个字段),它会返回 None 并添加到列表中。我宁愿它干净。
注意:我的所有字段都是文本。如果您的不同,请查看 calestini 提出的第三个解决方案。不过没有测试过。
columns = [
"foo",
"bar",
"foobar"
]
def list_everything(search):
d = {column: search for column in columns}
raw = [
model.query.filter(getattr(model, col).ilike(f"{val}%")).all()
for col, val in d.items()
]
return [item for item in raw if item]
如果我有更好的解决方案,我会继续优化和更新这段代码。非常感谢
【问题讨论】:
-
可能不是骗子,但至少这可以让您朝着正确的方向前进stackoverflow.com/questions/7942547/using-or-in-sqlalchemy。另外,还没有尝试过,但找到了一个有趣的过滤器链接pypi.org/project/sqlalchemy-filters
标签: python sqlalchemy flask-sqlalchemy