Skip to main content
 首页 » 编程设计

python之Django 通过列表中的值从数据库中查找项目

2024年09月07日32jpfss

我有一个字符串列表:

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

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

的短语

我试过这样的:

Phrase.objects.filter(name__in phrases_filter) 

但这只给了我名称中有 xx AND yy

的短语

请您参考如下方法:

我们可以展开列表,并定义一组 __contains带或逻辑的谓词:

from django.db.models import Q 
from functools import reduce 
from operator import or_ 
 
Phrase.objects.filter( 
    <b>reduce(or_, (Q(name__contains=e) for e in phrases_filter))</b> 
)

对于给定的 phrases_filter ,我们将生成等同于:

Phrase.objects.filter( 
    <b>Q(name__contains='xx') | Q(name__contains='yy')</b> 
)

所以 reduce(..)将在 Q(..) 的生成器 上运行对象,在这里 [Q(name__contains='xx'), Q(name__contains='yy')] . reduce(..)其工作方式类似于函数式编程中所谓的“折叠”(这是变形 的特例)。

因此我们将添加 or_介于两者之间,导致 Q(name__contains='xx') | Q(name__contains='yy') .这是一个基本上对过滤条件进行编码的对象:这意味着 name列应该__contains子字符串 'xx' ,或子字符串 'yy' .

Note: in case you want to match case insensitive (so rows with XX, or Xx, or xX, or xx are all candidates), then replace __contains with __<b>i</b>contains.

编辑:根据您的评论,以防phrases_filter为空,您希望所有行都匹配,我们可以使用 if 来做到这一点声明:

from django.db.models import Q 
from functools import reduce 
from operator import or_ 
 
queryset = Phrase.objects<b>.all()</b> 
<b>if phrases_filter:</b> 
    queryset = filter( 
        reduce(or_, (Q(name__contains=e) for e in phrases_filter)) 
    )

所以只有以防万一phrases_filter包含 至少 个元素,我们执行过滤。