Django按列表中的值从db中查找项目?

时间:2018-06-14 20:06:38

标签: python django python-3.x django-queryset

我有一个字符串列表:

phrases_filter = json.loads(request.GET['phrases_filter'])
['xx', 'yy']

我需要查找db中包含xx OR yy

的所有短语

我试过这样:

Phrase.objects.filter(name__in phrases_filter)

但这只给了我名字xx AND yy

的短语

1 个答案:

答案 0 :(得分:2)

我们可以展开列表,并使用or-logic定义一组__contains谓词:

from django.db.models import Q
from functools import reduce
from operator import or_

Phrase.objects.filter(
    reduce(or_, (Q(name__contains=e) for e in phrases_filter))
)

在给定phrases_filter的情况下,我们将生成相当于:

的内容
Phrase.objects.filter(
    Q(name__contains='xx') | Q(name__contains='yy')
)

所以reduce(..)将对Q(..)个对象的生成器进行操作,此处为[Q(name__contains='xx'), Q(name__contains='yy')]reduce(..)的工作方式类似于函数式编程中所知的" fold " (这是 catamorphism 的一个特例)。

我们将在其间添加or_,结果为Q(name__contains='xx') | Q(name__contains='yy')。这是一个基本上编码过滤条件的对象:它表示name列应该__contains子串'xx'或子串'yy'

  

注意:如果您想匹配敏感的案例(所以行包含XXXx或{{1} },或xX 所有候选人),然后将xx替换为__contains

编辑:根据您的评论,如果__icontains为空,您希望所有行都匹配,我们可以使用phrases_filter语句执行此操作:

if

因此,只有from django.db.models import Q from functools import reduce from operator import or_ queryset = Phrase.objects.all() if phrases_filter: queryset = filter( reduce(or_, (Q(name__contains=e) for e in phrases_filter)) )在元素上包含至少,我们才会执行过滤。