Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to prefetch_related on ClusterTaggableManager #139

Open
RealOrangeOne opened this issue Apr 14, 2021 · 1 comment
Open

Unable to prefetch_related on ClusterTaggableManager #139

RealOrangeOne opened this issue Apr 14, 2021 · 1 comment

Comments

@RealOrangeOne
Copy link
Member

Model set up:

@register_snippet
class MyTag(TagBase):
    free_tagging = False

    class Meta:
        ordering = ['name']


class MyRelation(ItemBase):
    tag = models.ForeignKey(MyTag, on_delete=models.CASCADE)
    content_object = ParentalKey(to='app.MyPage', on_delete=models.CASCADE)


class MyPage(Page):
    my_field = ClusterTaggableManager(through=MyRelation, verbose_name="My Relation")

Running MyPage.objects.prefetch_related('my_field') should work, but instead yields an error message which looks a lot like a bug rather than simple misuse:

(Paths redacted)

Traceback (most recent call last):
  File "blah/python3.8/site-packages/taggit/managers.py", line 71, in get_queryset
    return self.instance._prefetched_objects_cache[self.prefetch_cache_name]
AttributeError: 'NoneType' object has no attribute '_prefetched_objects_cache'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "blah/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "blah/python3.8/site-packages/django/core/handlers/base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "blah/python3.8/site-packages/django/core/handlers/base.py", line 143, in _get_response
    response = response.render()
  File "blah/python3.8/site-packages/django/template/response.py", line 106, in render
    self.content = self.rendered_content
  File "blah/python3.8/site-packages/django/template/response.py", line 83, in rendered_content
    content = template.render(context, self._request)
  File "blah/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "blah/python3.8/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 163, in _render
    return self.nodelist.render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "blah/python3.8/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "blah/python3.8/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "blah/python3.8/site-packages/django/template/defaulttags.py", line 308, in render
    if match:
  File "blah/python3.8/site-packages/django/core/paginator.py", line 150, in __len__
    return len(self.object_list)
  File "blah/python3.8/site-packages/django/db/models/query.py", line 256, in __len__
    self._fetch_all()
  File "blah/python3.8/site-packages/django/db/models/query.py", line 1244, in _fetch_all
    self._prefetch_related_objects()
  File "blah/python3.8/site-packages/django/db/models/query.py", line 771, in _prefetch_related_objects
    prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups)
  File "blah/python3.8/site-packages/django/db/models/query.py", line 1625, in prefetch_related_objects
    obj_list, additional_lookups = prefetch_one_level(obj_list, prefetcher, lookup, level)
  File "blah/python3.8/site-packages/django/db/models/query.py", line 1738, in prefetch_one_level
    prefetcher.get_prefetch_queryset(instances, lookup.get_current_queryset(level)))
  File "blah/python3.8/site-packages/taggit/managers.py", line 100, in get_prefetch_queryset
    self.get_queryset(query)
  File "blah/python3.8/site-packages/modelcluster/contrib/taggit.py", line 32, in get_queryset
    return super(_ClusterTaggableManager, self).get_queryset(extra_filters)
  File "blah/python3.8/site-packages/taggit/managers.py", line 74, in get_queryset
    return self.through.tags_for(self.model, self.instance, **kwargs)
  File "blah/python3.8/site-packages/taggit/models.py", line 112, in tags_for
    return cls.tag_model().objects.filter(**kwargs).distinct()
  File "blah/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "blah/python3.8/site-packages/django/db/models/query.py", line 892, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "blah/python3.8/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "blah/python3.8/site-packages/django/db/models/sql/query.py", line 1290, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "blah/python3.8/site-packages/django/db/models/sql/query.py", line 1315, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "blah/python3.8/site-packages/django/db/models/sql/query.py", line 1190, in build_filter
    lookups, parts, reffed_expression = self.solve_lookup_type(arg)
  File "blah/python3.8/site-packages/django/db/models/sql/query.py", line 1049, in solve_lookup_type
    _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
  File "blah/python3.8/site-packages/django/db/models/sql/query.py", line 1419, in names_to_path
    raise FieldError("Cannot resolve keyword '%s' into field. "
django.core.exceptions.FieldError: Cannot resolve keyword 'None' into field. Choices are: myrelation, mypage, id, name, slug

Prefetching by my_field__tag has the same result.

Given the stack, this might be an issue with taggit itself, but prefetch claims to be directly supported.

@chosak
Copy link
Member

chosak commented Dec 22, 2023

This error might be because your tag ForeignKey doesn't define a related_name. See taggit documentation here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants