Запросы Django: вернуть объект Q, который будет переводиться в «И (...)» - PullRequest
0 голосов
/ 08 июня 2018

Я пишу простой поиск для нашего сайта, и мне нужно отфильтровать записи по ряду критериев.Однако, если строгая фильтрация не выполняется, я хочу вернуть результаты для менее строгого поиска.Для этого я хочу создать несколько объектов запроса, каждый из которых будет иметь еще один фильтр, затем итерировать их в обратном порядке, пытаясь получить результат, и вернуть первый, полученный таким образом.

Что я делаю, это:

q0 = MyIndex.objects.in_city(city_id)
q1 = q0.filter(name_contains(words))

где

def name_contains(words):
    if not words:
        return Q()
    query = Q(words_contains=words[0])
    for word in word[1:]:
        query = query | Q(words_contains=word)

Когда я передаю слова, которых нет в базе данных, я все равно получаю результат,потому что часть запроса, возвращаемая name_contains, присоединяется через OR, а не AND.

Есть ли способ вернуть этот запрос, чтобы он всегда был присоединен к остальной части запроса с помощьюAND

1 Ответ

0 голосов
/ 08 июня 2018

Если у вас нет странного менеджера объектов, in_city, вероятно, преобразуется в .filter(..).

Если вы объедините несколько .filter(..) с, то вы неявно написали логические и между, так как ваш первый filter(..) фактически уже удаляет элементы, которые не удовлетворяют требованию, а ваш второй фильтр только фильтрует больше.

Вы можете проверить это подозрение, распечатав базовый запрос, Djangoвыполните с:

print(str(q0.filter(name_contains(words))<b>.query</b>))

Обратите внимание, что вы можете сделать свою функцию более декларативной, например:

from functools import reduce
from operator import or_

def name_contains(words):
    if words:
        return reduce(or_, (Q(word_contains=word) for word in words))
    else:
        return Q()
...