我正在尝试使用 SQLAlchemy ORM 实现动态过滤。
我在浏览 StackOverflow 时发现了非常相似的问题: SQLALchemy 动态 filter_by
这对我很有用,但还不够。
所以,在这里是一些代码示例,我正在尝试编写:
# engine - MySQL engine
session_maker = sessionmaker(bind=engine)
session = session_maker()
# my custom model
model = User
def get_query(session, filters):
if type(filters) == tuple:
query = session.query(model).filter(*filters)
elif type(filters) == dict:
query = session.query(model).filter(**filters)
return query
然后我尝试将其与非常相似的内容重用:
filters = (User.name == 'Johny')
get_query(s, filters) # it works just fine
filters = {'name': 'Johny'}
get_query(s, filters)
第二次运行后,出现了一些问题:
TypeError: filter() got an unexpected keyword argument 'name'
当我尝试时将我的
filters
更改为:
filters = {User.name: 'Johny'}
它返回:
TypeError: filter() keywords must be strings
但它对于手动查询工作正常:
s.query(User).filter(User.name == 'Johny')
我的过滤器出了什么问题?
顺便说一句,看起来它对于情况工作正常:| ||但是按照上述帖子的建议,我尝试仅使用
filters = {'name':'Johny'}
s.query(User).filter_by(**filters)
filter
如果只有一种可能使用
而不是
filter_by
,这两种方法之间有什么区别吗?
filter
, is there any differences between these two methods?
在尝试使用字典解包来构建 SQLAlchemy 查询过滤器时遇到了问题。SQLAlchemy 的
filter
方法被设计为接受关键字参数,其中关键字是列名(作为字符串),值是过滤条件。
以下是的代码中出现错误的原因以及如何更正它的说明:
错误分析
-
TypeError: filter() got an unexpected keyword argument 'name'
当传递
filters = {'name': 'Johny'}
并使用
filter(**filters)
时,Python 会尝试将字典解包为关键字参数。在这种情况下,它等效于调用
filter(name='Johny')
。但是,
filter
方法期望列名作为关键字参数的字符串,而不是 'name' 本身。
-
TypeError: filter() keywords must be strings
当传递
filters = {User.name: 'Johny'}
时,使用的是列对象 (
User.name
) 作为关键字,这在
filter
方法中是不允许的。
解决方案
为了解决这个问题,需要在使用字典解包之前构建一个包含正确关键字参数的字典:
def get_query(session, model, filters):
if isinstance(filters, dict):
# 将字典键转换为字符串列名
filters = {str(column.name): value for column, value in filters.items()}
query = session.query(model).filter_by(**filters)
elif isinstance(filters, tuple):
query = session.query(model).filter(*filters)
else:
raise ValueError("Invalid filters type. Must be dict or tuple.")
return query
# 使用示例
filters = {User.name: 'Johny'}
get_query(session, User, filters)
filter
与
filter_by
-
filter()
: 用于更复杂和动态的条件,接受 SQLAlchemy 表达式语言中的条件。可以使用比较运算符、逻辑运算符 (AND
,OR
,NOT
)、LIKE
、IN
等。 -
filter_by()
: 是filter()
的简化版本,用于简单的相等比较。它接受关键字参数,其中关键字是列名(作为字符串),值是用于相等比较的值。
总结
通过在使用字典解包之前正确格式化过滤器字典,可以使用
filter
或
filter_by
方法轻松地构建动态 SQLAlchemy 查询。选择哪种方法取决于需要的查询复杂度。