0

In Wagtail I want to get a list of Tags, each with a count of the number of Pages tagged, but only counting live() pages.

Let's say I have this set-up, from the docs:

from django.db import models
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TagBase, ItemBase

class BlogTag(TagBase):
    class Meta:
        verbose_name = "blog tag"
        verbose_name_plural = "blog tags"


class TaggedBlog(ItemBase):
    tag = models.ForeignKey(
        BlogTag, related_name="tagged_blogs", on_delete=models.CASCADE
    )
    content_object = ParentalKey(
        to='demo.BlogPage',
        on_delete=models.CASCADE,
        related_name='tagged_items'
    )

class BlogPage(Page):
    ...
    tags = ClusterTaggableManager(through='demo.TaggedBlog', blank=True)

I can get a list of BlogTags, each with a count of the number of BlogPages tagged with it, by doing this (I think that's what it's doing...?):

from django.db.models.aggregates import Count

BlogTag.objects.annotate(count=Count("tagged_blogs"))

But I can't get my head round how to filter this to only count pages that are live() (or that have some other Page-related quality).

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143

1 Answers1

0

I think this two-stage process works. First get all the Page IDs filtered by whatever you need, like live(). Then filter the BlogTags by those

page_ids = Page.objects.live().values_list("id", flat=True)

BlogTag.objects.filter(
    tagged_blogs__content_object_id__in=page_ids
).annotate(count=Count("tagged_blogs"))

I thought I'd have to filter the second query to only get BlogTags with a count greater than 0 but it doesn't include tags with no pages anyway.

I don't know if this is the best solution, given it starts with having to get a list of all live pages, so maybe there's a better solution?

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143