Значок django с __in lookup
Итак, я хочу найти любое соответствие, соответствующее некоторым полям, так, например, это то, что я хотел бы сделать:
possible_merchants = ["amazon", "web", "services"]
# Possible name --> "Amazon Service"
Companies.objects.filter(name__icontains__in=possible_merchants)
К сожалению, невозможно комбинировать значки и поиск __in.
Кажется, это довольно сложный запрос, так что, по крайней мере, я мог бы игнорировать случай, которого было бы достаточно, например:
Companies.objects.filter(name__ignorecase__in=possible_merchants)
Любые идеи?
P.D.: Запросы, которые я написал, не работают, это просто способ выразить то, что мне нужно (на всякий случай, хех)
Ответы
Ответ 1
Вы можете создать запрос с конструктором Q
и объединить их с оператором |
, чтобы получить их объединение:
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
.)
Ответ 2
Я считаю, это более чистый подход с использованием 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
имеющему несколько OR, которые могут быть непосредственно применены к запросу фильтра.
Ответ 3
Это подход, который я принял:
class MyManager(models.Manager):
def exclusive_in(self, lookup, value_list):
return self.filter(reduce(or_, (Q(**{lookup:_}) for _ in value_list)))
Он основан на наборе запросов фильтра Django __in для * каждого * элемента в списке и других предложениях в этой теме.
Вот теперь, чтобы использовать это:
Companies.objects.exclusive_in('name__icontains', possible_merchants])