Reputation: 907
Explanation
I would like to add to SearchView
a filter that checks tags in my models and if raw_query
contains tag then it displays the list of relevant objects.
Each model contains title and tags fields. I am using django taggit with autosugest extension to handle tags in my application.
For instance user is inserting tag1 into a search bar and MyModel1
contains a tag like this then it should appear on the page. If not then my SearchView
is checking if rank
returns anything and return list of relevant objects.
Problem
tag_query
is always returning empty list. I checked database and tags are added correctly. I can display them in Django templates properly but my tag_query
return empty list of tags.
Question
How can I implement tags filter properly so based on users query it will check list of tags and return objects that contain this tag.
Code
models.py
from taggit_autosuggest.managers import TaggableManager
class MyModel1(models.Model):
title = models.CharField('Title', max_length=70, help_text='max 70 characters', unique=True)
tags = TaggableManager()
...
views.py
class SearchView(LoginRequiredMixin, CategoryMixin, ListView, FormMixin, PostQuestionFormView):
model = MyModel1
template_name = 'search/SearchView.html'
context_object_name = 'results'
form_class = PostQuestionForm
def get_queryset(self):
models = [MyModel1, MyModel2, MyModel3]
vectors = [SearchVector(f'title', weight='A') + SearchVector(f'short_description', weight='B') for model in models]
queries = []
for model, vector in zip(models, vectors):
raw_query = self.request.GET.get("q")
query = SearchQuery(raw_query, config='english')
rank = SearchRank(vector, query)
headline = SearchHeadline('title', query, start_sel='<span class="text-decoration-underline sidebar-color">',stop_sel='</span>', highlight_all=True)
# Filter by tags using Django Q filter
tag_query = Q(tags__name__icontains=raw_query_split)
# First check if raw_query contains a tag and display list of objects with matching tag
if tag_query:
queryset = model.objects.annotate(rank=rank, headline=headline).filter(tag_query)
print("tag: ", queryset)
# If tag is not found then use SearchVector, SearchQuery and SearchRank to search for objects matching words in raw_query
if rank:
queryset = model.objects.annotate(rank=rank, headline=headline).filter(rank__gte=0.3)
print("rank: ", queryset)
queries.append(queryset)
results = list(chain(*queries))
results = sorted(results, key=lambda x: (-x.rank, x.headline))
result_count = len(results)
return results
Upvotes: 2
Views: 108