Django taggit view, приводящий к FieldError: Related Field got invalid lookup: name
Вид тегов приводит к этому сообщению об ошибке.
FieldError: Related Field got invalid lookup: name
указывает на несоответствие между тем, что Django ORM ожидает от запроса к отношению tags, и реальным выполняемым запросом.
[...]
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
Я пробовал получить экземпляр тега по его слогу и использовать имя полученного экземпляра тега для фильтрации объектов вопроса.
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
Ошибка возникает из-за того, что метод Django filter()
используется с tags__name
, что не является корректным поиском для связи тегов, установленной django-taggit
.
django-taggit не хранит теги непосредственно в модели, а использует сквозную модель для связывания тегов с объектами. Это означает, что вы не можете напрямую использовать tags__name
или tags__slug
в вызове filter()
, по крайней мере, в большинстве очевидных случаев.
Этот подход подтвердил свою работоспособность, он включал использование модели TaggedItem от taggit для поиска всех элементов, помеченных определенным тегом, а затем фильтрацию объектов Question на основе этого:
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