[英]django icontains with __in lookup
So I want to find any kind of matching given some fields, so for example, this is what I would like to do:所以我想在给定一些字段的情况下找到任何类型的匹配,例如,这就是我想要做的:
possible_merchants = ["amazon", "web", "services"]
# Possible name --> "Amazon Service"
Companies.objects.filter(name__icontains__in=possible_merchants)
sadly it is not possible to mix icontains and the __in lookup.遗憾的是,不能混合使用 icontains 和 __in 查找。
It seems to be a pretty complex query so if at least I could ignore case the name that would be enough, for example:这似乎是一个非常复杂的查询,所以如果至少我可以忽略大小写就足够了,例如:
Companies.objects.filter(name__ignorecase__in=possible_merchants)
Any ideas?有任何想法吗?
PD: The queries I posted don't work, it's just a way to express what I need (just in case heh) PD:我发布的查询不起作用,这只是表达我需要的一种方式(以防万一)
You can create querysets with the Q
constructor and combine them with the |
您可以使用
Q
构造函数创建查询集并将它们与|
operator to get their union:运营商获得他们的工会:
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)
(And similarly with iexact
instead of icontains
.) (同样使用
iexact
而不是icontains
。)
I find it a cleaner approach using reduce
and or_
operator:我发现使用
reduce
和or_
运算符是一种更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)
This would create a list of Q
objects querying the name
to contain a single element in merchant list.这将创建一个
Q
对象列表,查询name
以包含商家列表中的单个元素。 This would happpen for all the elements in merchant_list
and all these Q
objects would be reduced to a single Q
object having mutliple ORs which can be directly applied to the filter query.这将适用于
merchant_list
所有元素,并且所有这些Q
对象都将减少为具有多个OR 的单个Q
对象,这些OR 可以直接应用于过滤器查询。
This is the approach that I adopted:这是我采用的方法:
class MyManager(models.Manager):
def exclusive_in(self, lookup, value_list):
return self.filter(reduce(or_, (Q(**{lookup:_}) for _ in value_list)))
Here is now to use it:现在使用它:
Companies.objects.exclusive_in('name__icontains', possible_merchants])
It was inspired by other answers in this thread, as well as Django filter queryset __in for *every* item in list .它的灵感来自该线程中的其他答案,以及Django filter queryset __in for *every* item in list 。
Another approach would be to simulate the actions that Django normally does for iexact
queries (it converts both parts of the comparison statement to the upper case via SQL Upper function.另一种方法是模拟 Django 通常对
iexact
查询执行的操作(它通过 SQL Upper 函数将比较语句的两个部分都转换为大写。
This way, the query will look like this:这样,查询将如下所示:
Companies.objects.annotate(
upper_name=models.Upper("name")
).filter(
upper_name__in=[rchant.upper() for merchant in possible_merchants]
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.