Django通过列表中的值从数据库中查找项目?
Posted
技术标签:
【中文标题】Django通过列表中的值从数据库中查找项目?【英文标题】:Django find items from db by values from list? 【发布时间】:2018-11-24 16:21:24 【问题描述】:我有一个字符串列表:
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】:我们可以展开列表,并用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(..)
的工作方式类似于 函数式编程 中已知的“折叠”(这是 catamorphism 的一个特例)。
因此,我们将在两者之间添加or_
s,从而得到Q(name__contains='xx') | Q(name__contains='yy')
。这是一个基本上对过滤条件进行编码的对象:这意味着name
列应该__contains
子字符串'xx'
,或子字符串'yy'
。
注意:如果你想匹配大小写敏感(所以行带有
XX
,或Xx
,或xX
,或xx
是所有个候选),然后将__contains
替换为__<b>i</b>contains
。
编辑:根据您的评论,如果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))
)
所以只有在phrases_filter
元素上包含至少的情况下,我们才会执行过滤。
【讨论】:
你能不能逐行解释,我不太明白它是怎么工作的,这是什么意思 这个phrases_filter也可以为空 @user2950593:如果它是空的,那会发生什么?没有匹配,还是所有行都匹配? 所有行匹配=) 好的,似乎正在工作=) 这是完成这项任务的首选方式吗?以上是关于Django通过列表中的值从数据库中查找项目?的主要内容,如果未能解决你的问题,请参考以下文章