Построение запроса постепенно в Pony ORM - PullRequest
0 голосов
/ 17 сентября 2018

Я оцениваю переход с 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похоже, есть только (довольно умный!) генератор синтаксических анализаторов AST и необработанный 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, или имея механизм, с помощью которого я передаю запрос для фильтрации другим подзапросом.)

1 Ответ

0 голосов
/ 18 сентября 2018

В PonyORM есть два способа пошагового составления запроса. Первый метод filter запроса:

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 с переменным числом подвыражений, в данный момент у Pony нет API для этого. Возможно, мы добавим возможность постепенно добавлять подвыражения к предложению or в будущих выпусках.

...