Django taggit view leading to FieldError: Related Field got invalid lookup: name

42 Views Asked by At

Tag view leads to this error message. The FieldError: Related Field got invalid lookup: name indicates a mismatch between what the Django ORM expects for a query on the tags relation and the actual query being executed.

[...]
 File "/workspace/Coach-Matrix/main_forum/views/filters.py", line 18, in get_queryset
    return Question.objects.filter(tags__name=tag.name)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/query.py", line 1420, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/query.py", line 1438, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/query.py", line 1445, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1532, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1562, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1478, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/workspace/.pip-modules/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1292, in build_lookup
    raise FieldError(

Exception Type: FieldError at /questions/tag/tag4/
Exception Value: Related Field got invalid lookup: name

I had tried Fetching the Tag instance using its slug and Using the name of the fetched Tag instance to filter Question objects.

from django.views.generic.list import ListView
from ..models import Question
from django.shortcuts import get_object_or_404
from taggit.models import Tag

class FilterByTagView(ListView):
    model = Question
    template_name = 'filtered_questions.html'
    context_object_name = 'questions'

    def get_queryset(self):
        tag_slug = self.kwargs.get('tag_slug')
        # Retrieve the Tag object by slug
        tag = get_object_or_404(Tag, slug=tag_slug)
        # Use TaggedItemManager's filter method to get questions tagged with the retrieved tag
        return Question.objects.filter(tags__slug=tag.slug)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        tag_slug = self.kwargs.get('tag_slug')
        context['tag'] = get_object_or_404(Tag, slug=tag_slug)
        return context
1

There are 1 best solutions below

0
Laurie Crean On

The error arises because the Django filter() method is being used with tags__name, which isn't a valid lookup for the tags relation established by django-taggit.

django-taggit doesn't store tags directly on the model but instead uses a through-model to associate tags with objects. This means you cannot directly use tags__name or tags__slug in a filter() call, at least for most obvious cases.

This approach confirmed as working, it involved using taggit's TaggedItem model to find all items tagged with a specific tag and then filtering the Question objects based on that:

from django.views.generic.list import ListView
from ..models import Question
from django.shortcuts import get_object_or_404
from taggit.models import Tag, TaggedItem # added Taggeditem to find all items tagged with a specific tag

class FilterByTagView(ListView):
    model = Question
    template_name = 'filtered_questions.html'
    context_object_name = 'questions'

    def get_queryset(self):
        tag_slug = self.kwargs.get('tag_slug')
        tag = get_object_or_404(Tag, slug=tag_slug)

        # Use TaggedItem to query all items associated with the tag:
        questions_ids = TaggedItem.objects.filter(tag_id=tag.id).values_list('object_id', flat=True)

        return Question.objects.filter(id__in=questions_ids) # return id in question_id's

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        tag_slug = self.kwargs.get('tag_slug')
        context['tag'] = get_object_or_404(Tag, slug=tag_slug)
        return context