当前位置: 代码迷 >> python >> 在Pony ORM中逐步建立查询
  详细解决方案

在Pony ORM中逐步建立查询

热度:10   发布时间:2023-07-14 08:57:45.0

我正在评估从peewee切换到Pony ORM的过程。 在peewee中可用的一件好事是能够从这样的部分组成查询:

def Entry(BaseModel):
    # peewee fields go here

def where_entry_category(category, recurse=False):
    """ Generate a where clause for a particular category """

    if category or not recurse:
        cat_where = (Entry.category == str(category))

        if recurse:
            # We're recursing and aren't in /, so add the prefix clause
            cat_where = cat_where | (
                Entry.category.startswith(str(category) + '/'))
    else:
        cat_where = True

    return cat_where

query = Entry.select().where(where_entry_category("test"))

这种工作方式是在peewee模型类型上的各种运算符重载仅返回查询组件树,而这些子树可以由进一步的运算符重载组成。 具有多个与&|链接在一起的查询组件也很简单| 运算符,例如model.Entry.select().where(some_test() & some_other_test()) 这非常有用,因为我的许多过滤查询都是以模块化方式构成的,并且大多数基础查询部分经常被重用,并且许多都是不平凡的(例如上述示例)。

但是,在Pony ORM中,似乎只有(相当聪明!) 和原始SQL。 由于原始SQL格式无法让我直接传递必要的查询部分,因此,我将尽可能使用一些更高级别的查询构建功能。

如果我尝试将查询部分定义为模型上的方法,例如:

class Entry(db.Entity):
    ...
    def in_category(self, category, recurse=False):
        # return a test on the parameters

orm.select(entry for entry in model.Entry if entry.in_category('foo', True)) 

毫不奇怪,我得到NotImplementedError

是否有一种机制可以从现有零件构建查询表达式,并传递给SQL查询生成器? (也许是通过自己构建AST并将其传递到Pony的相关部分,或者使用一种机制来传递查询以被另一个子查询过滤)。

在PonyORM中,有两种方法可以逐步组成查询。 第一个是查询的方法:

def where_entry_category(query, category, recourse)
    if category:
        category = str(category)
        if recurse:
            query = query.filter(lambda x: x.category == category or
                                 x.category.startswith(category + '/')
        else:
            query = query.filter(lambda x: x.category == category)
    return query

query = Entry.select()
query = where_entry_category(query, "test")

从0.7.6版本开始,还可以使用以前的查询作为新查询的源:

def where_entry_category(query, category, recourse)
    if category:
        category = str(category)
        if recurse:
            query = select(x for x in query
                           if x.category == category or
                              x.category.startswith(category + '/'))
        else:
            query = select(x for x in query if x.category == category)
    return query

你可能会遇到的唯一问题是,如果你想逐步建立or有可变数量的子表达式,在这一刻小马没有API的that从句。 也许我们会在将来的发行版中增加向or子句中逐渐添加子表达式的可能性。