所以我想在某些字段中找到任何类型的匹配,例如,这就是我想要做的事情:
possible_merchants = ["amazon", "web", "services"]
# Possible name --> "Amazon Service"
Companies.objects.filter(name__icontains__in=possible_merchants)
遗憾的是,无法混合icontains和__in查找。
这似乎是一个非常复杂的查询,所以如果至少我可以忽略大小足够的名称,例如:
Companies.objects.filter(name__ignorecase__in=possible_merchants)
有什么想法吗?
P.D。:我发布的查询不起作用,这只是一种表达我需要的方式(以防万一)
答案 0 :(得分:25)
您可以创建查询集with the Q
constructor并将它们与|
运算符组合以获得它们的联合:
from django.db.models import Q
def companies_matching(merchants):
"""
Return a queryset for companies whose names contain case-insensitive
matches for any of the `merchants`.
"""
q = Q()
for merchant in merchants:
q |= Q(name__icontains = merchant)
return Companies.objects.filter(q)
(类似于iexact
而不是icontains
。)
答案 1 :(得分:1)
我发现它使用reduce
和or_
运算符是一种更干净的方法:
from django.db.models import Q
from functools import reduce
from operator import or_
def get_companies_from_merchants(merchant_list):
q_object = reduce(or_, (Q(name__icontains=merchant) for merchant in merchant_list))
return Companies.objects.filter(q_object)
这将创建Q
个对象的列表,这些对象查询name
以在商家列表中包含一个元素。这将发生merchant_list
中的所有元素,并且所有这些Q
对象将被简化为具有多个或可以直接应用于过滤器查询的单个Q
对象。
答案 2 :(得分:0)
这是我采用的方法:
class MyManager(models.Manager):
def exclusive_in(self, lookup, value_list):
return self.filter(reduce(or_, (Q(**{lookup:_}) for _ in value_list)))
现在在这里使用它:
Companies.objects.exclusive_in('name__icontains', possible_merchants])
它是受此主题中其他答案以及Django filter queryset __in for *every* item in list启发的。
答案 3 :(得分:0)
另一种方法是模拟 Django 通常对 iexact
查询执行的操作(它通过 SQL Upper 函数将比较语句的两部分都转换为大写。
这样,查询将如下所示:
Companies.objects.annotate(
upper_name=models.Upper("name")
).filter(
upper_name__in=[rchant.upper() for merchant in possible_merchants]
)