In my django-project have a search function where you can specify tags, like "apple, banana" and by that query for objects of a certain model, tagged with taggit
. When I do:
tag_set = Tag.objects.filter(Q(name__in=tag_list))
query_set = Model.objects.filter(Q(tags__in=tag_set))
this gives me objects tagged with either "apple" OR "banana". But I want the AND operator... I tried:
query_set = Model.objects.filter(reduce(operator.and_, (Q(tags__in=x) for x in tag_set)))
but then I get 'Tag' object is not iterable
.
Any help?
CodePudding user response:
You can work with:
queryset = Model.objects.all()
for tag in tag_list:
queryset = queryset.filter(tags__name=tag)
This will make a JOIN
for each tag, and thus eventually the queryset
will only contain Model
items that have all the necessary tags.
Another approach is counting the number of matched tags, so:
from django.db.models import Count
tag_set = set(tag_list)
Model.objects.filter(tag__name__in=tag_set).alias(
ntags=Count('tags')
).filter(ntags=len(tag_set))