Как построить динамический Q() в Django

Я пытаюсь отфильтровать динамическое значение из формы в шаблоне в мой запрос в проекте Django

значение может быть динамическим, но оно будет выглядеть следующим образом

first_query = ['a', 'b', 'c']
second_query = ['d', 'e', 'f']

Что я хочу достичь, так это запросить что-то вроде этого

SELECT * FROM table WHERE column_1 = 'a' OR column_1 = 'b' OR column_1 = 'c' OR column_2 = 'd' OR column_2 = 'e' OR column_2 = 'f'

Вот что я сделал

        first_query = [ Q(column_1__contains=w) for w in first_query ]

        """
        If you print first_query
        [<Q: (AND: ('column_1__contains', 'a'))>, <Q: (AND: ('column_1__contains', 'b'))>, 
          <Q: (AND: ('column_1__contains', 'c'))>]
        """


        reduce_first_query = reduce(or_, query_first_query)
        """
        (OR: ('column_1', 'a'), ('column_1', 'b'),('column_1', 'c'))
        """
        

        second_query = [ Q(column_2__contains=w) for w in second_query ]
        reduce_second_query = reduce(or_, query_second_query)

Когда я пытаюсь отфильтровать элемент из моей базы данных, это дает мне строки более чем в два раза больше, чем то, что я делаю непосредственно из базы данных

test_item = Item.objects.filter(reduce_first_query) # Gives 1900 ish rows, should be 900 ish

Что я делаю не так, это из-за того, как я строю Q()? Или есть другие ошибки?

NOTES

  • Я использую Postgresql 14

Для построения динамического объекта Q в Django можно использовать класс Q и его методы для динамического построения условия запроса.

Например, если у вас есть список ключевых слов для поиска и вы хотите создать объект Q, который соответствует любому из этих ключевых слов, вы можете использовать метод Q.or_ для объединения нескольких объектов Q в один запрос. Вот пример:

from django.db.models import Q
keywords = ['apple', 'banana', 'cherry']
q = Q()
for keyword in keywords:
    q |= Q(name__contains=keyword)
results = MyModel.objects.filter(q)

В этом примере переменная q изначально устанавливается в пустой объект Q. Затем в цикле выполняется итерация по списку ключевых слов и используется метод Q.or_ для объединения нового объекта Q для каждого ключевого слова в объект q.

Объект Q, создаваемый для каждого ключевого слова, использует аргумент ключевого слова name__contains для поиска любых объектов MyModel, имеющих поле name, содержащее ключевое слово.

В конце переменная results будет содержать все объекты MyModel, которые соответствуют любому из ключевых слов в списке.

Вы можете использовать ту же технику для создания динамических объектов Q для других условий запроса и комбинаций условий. Класс Q предоставляет множество методов и операторов, которые вы можете использовать для динамического построения сложных условий запроса.

Для получения указанного вами запроса необходимо в искать, а не содержит:

first_query = ['a', 'b', 'c']
second_query = ['d', 'e', 'f']

qs = Item.objects.filter(Q(column1__in=first_query) | Q(columns2__in=second_query))

И кстати, вы можете просмотреть SQL-запрос, созданный ORM, следующим образом:

print(qs.query)
Вернуться на верх