'In Wagtail, get counts of Pages in each Tag, but only counting live() Pages
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).
Solution 1:[1]
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?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Phil Gyford |
