Adrian
Adrian

Reputation: 907

Django taggit returns empty list of tags in search view

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

Answers (0)

Related Questions