Как построить динамический 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)