django icontains с поиском __in - PullRequest
       1

django icontains с поиском __in

14 голосов
/ 13 марта 2012

Итак, я хочу найти любой вид сопоставления с некоторыми полями, например, вот что я хотел бы сделать:

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)

Есть идеи?

PD: Запросы, которые я отправил, не работают, это просто способ выразить то, что мне нужно (на всякий случай, хе)

Ответы [ 3 ]

25 голосов
/ 13 марта 2012

Вы можете создать наборы запросов с помощью конструктора 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.)

1 голос
/ 29 июня 2018

Я считаю, что более чистый подход с использованием операторов 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, которые могут быть непосредственно применены к запросу фильтра.

0 голосов
/ 03 июля 2019

Я выбрал этот подход:

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 __in для * каждого * элемента в списке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...