Создание запроса FIQL с peewee - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь создать функцию, которая будет принимать отформатированную строку FIQL и возвращать выражение peewee .

Допустим, у меня есть параметры URL в FIQLформат выглядит так:

fiql_str = "name==Foo,(country==USA;city==Kansas)"

Использование FIQL Parser Я могу вернуть этот объект:

['OR', ('name', '==', 'Foo'), ['AND', ('country', '==', 'USA'), ('city', '==', 'Kansas')]]

Я бы хотел сделать следующее:создать функцию, которая принимает вышеуказанный объект и создает выражение, которое может понять peewee.Я привык к django & Q объектам , где я могу связать вместе выражения, например, так:

fm = Q()
for mapping in mappings:
    fm |= Q(subscription__approver=mapping.user)
return self.filter(fm)

Я пытался подражать этому с помощью Query Builder / Node * peewee1021 * вот так:

def map_to_filter(expressions, node):
    expression = expressions.pop(0)
    if type(expression) == str:
        if expression == "OR":
            node |= map_to_filter(expressions, node)
        if expression == "AND":
            node &= map_to_filter(expressions, node)
    elif type(expression) == tuple:
        return getattr(Store, expression[0]) + expression[1] + expression[2]
    elif type(expression) == list:
        map_to_filter(expression, node)
    return node

result = map_to_filter(expressions, peewee.Node())

Но я получаю NotImplementedError:

/lib/python3.7/site-packages/peewee.py in __sql__(self, ctx)
    616
    617     def __sql__(self, ctx):
--> 618         raise NotImplementedError
    619
    620     @staticmethod

NotImplementedError:

Возможно ли построить такую ​​функцию?В противном случае, какие еще инструменты / плагины доступны для устранения этой проблемы?

1 Ответ

0 голосов
/ 06 февраля 2019

Ваша проблема связана с использованием чистого Node, который не соответствует ни одному из SQL (следовательно, нет sql метода).

Я бы предложил накопить список и использоватьfunctools.reduce(), чтобы объединить их.

например,

list_of_conds = [
    (model.field1 == 'val1'),
    (model.field2 == 'bar')]
reduce(operator.and_, list_of_conds)

Вы можете переключить свою функцию уменьшения на operator.or_, где это необходимо, и продолжить поиск в глубину, как у вас.

...