[英]Building a FIQL query with peewee
I'm attempting to create a function that will take a FIQL formatted string and return a peewee expression. 我正在尝试创建一个函数,该函数将采用FIQL格式的字符串并返回peewee表达式。
Let's say I have url params in FIQL format like so: 假设我有FIQL格式的网址参数,如下所示:
fiql_str = "name==Foo,(country==USA;city==Kansas)"
Using a FIQL Parser I am able to get this object back: 使用FIQL解析器,我可以找回该对象:
['OR', ('name', '==', 'Foo'), ['AND', ('country', '==', 'USA'), ('city', '==', 'Kansas')]]
What I'd like to do, is to create a function that takes the above object, and creates an expression that peewee can understand. 我想做的是创建一个接受上述对象的函数,并创建一个peewee可以理解的表达式。 I'm used to django & Q objects , where I can chain together expressions like so: 我习惯于django&Q objects ,在这里我可以像这样将表达式链接在一起:
fm = Q()
for mapping in mappings:
fm |= Q(subscription__approver=mapping.user)
return self.filter(fm)
I've tried mimicking this with peewee's Query Builder / Node like so: 我试图用peewee的Query Builder / Node来模仿它,如下所示:
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())
But I am getting a NotImplementedError: 但我收到一个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:
Is it possible to build such a function? 是否可以构建这样的功能? Otherwise, what other tools/pluggins are available for troubleshooting this? 否则,还有哪些其他工具/插件可用于对此进行故障排除?
Your issue comes from using a bare Node
, which does not correspond to any SQL (hence, no sql method). 您的问题来自使用裸Node
,它与任何SQL不对应(因此,没有sql方法)。
I'd suggest accumulating a list and using functools.reduce()
to combine them. 我建议积累一个列表,并使用functools.reduce()
组合它们。
eg, 例如,
list_of_conds = [
(model.field1 == 'val1'),
(model.field2 == 'bar')]
reduce(operator.and_, list_of_conds)
You can switch your reduce function to be operator.or_ where necessary and proceed using a depth-first search, as you have. 您可以根据需要将reduce函数切换为operator.or_,并继续使用深度优先搜索。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.