Skip to content

Unable to prefetch_related on ClusterTaggableManager #139

@RealOrangeOne

Description

@RealOrangeOne

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions