django как динамически создавать вложенные и / или запросы - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть два типа списка фильтров, как показано ниже

a_filter = ['a', 'b', 'c']
b_filter = ['x', 'y', 'z']

Мне нужно объединить запрос in для a_filter и запрос логического поля для b_filter что-то вроде ниже

Item.objects.filter(a__in=a_filter, x=True, y=True, z=True)

Как мне динамически создать этот запрос? Я дошел до следующего:

filters = {
  a_filter__in:a_filter,
}

and_condition = Q(**filters)

if len(b_filter) > 0:
  or_cond = Q()
  for filter in b_filter:
    or_cond.add(Q(**{filter:True}), Q.AND)

and_condition.add(or_filter)

Item.objects.filter(and_condition)

Это создает дополнительные (OR: (AND: ) между двумя запросами фильтра, как показано ниже

(AND: 'a_filter__in': ['a', 'b', 'c'), (OR: (AND: ), (AND:('x':True, 'y':True, 'z':True))

Как мне написать правильно работающий запрос?

1 Ответ

0 голосов
/ 20 февраля 2020

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

Этого будет достаточно:

bool_kwargs = {k: True for k in b_filter}
Item.objects.filter(a__in=a_filter, **bool_kwargs)

Кроме того, приведенный вами пример будет не работа. Предполагая, что вы имели в виду что-то вроде:

filters = {
    "a__in": a_filter,
}

and_condition = Q(**filters)

if len(b_filter) > 0:
    or_cond = Q()
    for filter in b_filter:
        or_cond.add(Q(**{filter: True}), Q.AND)

    and_condition.add(or_cond)

Item.objects.filter(and_condition)

Если вы все равно хотите использовать Q объекты или что Q.AND должен быть Q.OR (как намекнуло имя переменной or_cond) , вы можете сделать:

from functools import reduce
from operator import or_ # replace or_ with and_ for Q.AND

bool_q_list = [Q(k=True) for k in b_filter]
bool_q = reduce(or_, bool_q_list) # replace or_ with and_ for Q.AND
Item.objects.filter(bool_q, a__in=a_filter)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...