我正在使用嵌套的AND/OR逻辑创建动态过滤器,并希望将NOT作为一个选项。这利用Q对象来创建嵌套的AND/OR逻辑。
该类接收一个json对象,如下所示:
filters = {
'and': {
"url__is": "www.test.com",
"name__is": "test"
}
}
这被编译成
.filter(Q(url__is='www.test.com') and Q(name__is='test')
这是通过一个递归函数实现的,该函数实际上只是在json树的每个级别上实现这一点。
return source_queryset.filter(reduce(and_, filter_list))
and_来自python操作符库,并且一直运行良好。不过,我也想添加NOT作为一个选项,而且似乎找不到将Q对象列表减少为.的等效选项
有人知道用reduce来创建不等于q对象列表的想法吗?
您正在Q
对象上查找~
运算符,这是一个复杂的查找。
最后你会得到这样的东西:
.filter(~Q(url__is='www.test.com'))
要匹配递归函数,应该使用inv
或invert
运算符。因为它在使用~
运算符时匹配所需的输出。
>>> from django.db.models import Q
>>> from operator import inv
>>> ~Q()
<Q: (NOT (AND: ))>
>>> inv(Q())
<Q: (NOT (AND: ))>
所以你可以在递归函数中使用它,比如
return source_queryset.filter(map(inv, filter_list))
您可以通过在任何Q对象前面应用~
运算符来翻转它。
.exclude(Q(id=5))
与相同
.filter(~Q(id=5))
您应该能够在计算filter_list
时使用此选项。