sqlalchemy 动态过滤

新手上路,请多包涵

我正在尝试使用 SQLAlchemy ORM 实现动态过滤。

我正在浏览 StackOverflow 并发现了非常相似的问题: SQLALchemy dynamic 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 ,这两种方法之间有什么区别吗?

原文由 smart 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

您的问题是 filter_by 采用关键字参数,但 filter 采用表达式。因此,为 filter_by **mydict 扩展字典将起作用。对于过滤器,您通常会向它传递一个参数,该参数恰好是一个表达式。因此,当您将 **filters dict 扩展到过滤器时,您向过滤器传递了一堆它不理解的关键字参数。

如果您想从存储的过滤器参数的字典中构建一组过滤器,您可以使用查询的生成特性来继续应用过滤器。例如:

 # assuming a model class, User, with attributes, name_last, name_first
my_filters = {'name_last':'Duncan', 'name_first':'Iain'}
query = session.query(User)
for attr,value in my_filters.iteritems():
    query = query.filter( getattr(User,attr)==value )
# now we can run the query
results = query.all()

上述模式的好处在于您可以在多个连接的列中使用它,您可以使用 and_ 和 or_ 构造“ands”和“ors”,您可以进行 <= 或日期比较,等等。它比使用带关键字的 filter_by 灵活得多。唯一需要注意的是,对于连接,您必须小心一点,不要不小心尝试连接一个表两次,并且您可能必须为复杂的过滤指定连接条件。我在一个非常复杂的域模型上使用它进行一些非常复杂的过滤,它就像一个魅力一样工作,我只是保持一个 entities_joined 的字典来跟踪连接。

原文由 Iain Duncan 发布,翻译遵循 CC BY-SA 3.0 许可协议

我有一个类似的问题,试图从字典中过滤:

 filters = {"field": "value"}

错误的:

 ...query(MyModel).filter(**filters).all()

好的:

 ...query(MyModel).filter_by(**filters).all()

原文由 Ivan Camilito Ramirez Verdes 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏