Немного неортодоксально, но вы можете использовать рекурсию. Итак, в вашем примере:
def recursive_search(tags, results_queryset):
if len(tags) > 0:
result_qs = result_queryset.filter(tags_name=tags[0])
if result_queryset.exists():
return filter_recursion(tags[1:],result_queryset)
else:
return None
return result_queryset
tags = ["comedy", "80s", "action", "thriller"] # This can be variable
result_queryset = Item.objects.filter(brands__in=brands) # Could be Item.objects.all()
print recursive_search(tags, result_queryset)
Итак, вы начинаете со списка тегов, которые вы ищете, и набора запросов ВСЕХ ваших товаров, которые могут соответствовать вашим критериям (в данном случае мы начинаем со списка товаров определенной марки)
Затем вы рекурсивно просматриваете список тегов один за другим и сокращаете набор запросов. Для каждого уровня вы повторно фильтруете весь набор запросов только для тех элементов, которые имеют все упомянутые теги.
так:
- первый вызов / уровень будет для всех предметов, имеющих тег любимый ,
- второй вызов / уровень будет для всех предметов, имеющих теги любимый и самый громкий ,
- и т.д.
Если набор запросов, возвращаемый фильтром, равен None, это означает, что нет элементов, которые имеют все необходимые теги, и метод завершит работу и вернет None (т.е. он завершится при первом возможном случае сбоя). Кроме того, должен быть только один удар по базе данных (я думаю!)
Я проверил это, и оно должно работать, так что попробуйте
EDIT
Чтобы объединить набор запросов, возвращенный из брендов (q1), и набор запросов, созданный выше, с помощью itertools (q2):
list = []
for item in itertools.chain(q1, q2):
list.append(item)
РЕДАКТИРОВАТЬ 2
Разве это не выполняет то, что вам нужно в одном запросе?
# list of tags = ['comedy','80s']
qs = Item.objects.all( Q(brand__iexact="brand name") | Q(tags__name__in=[tag for tag in list_of_tags]) )