Reputation: 11052
Let's say I have the following django model:
class Tag(models.Model):
key = models.CharField(max_length=64, unique=True)
class Site(models.Model):
key = models.CharField(max_length=64, unique=True)
tags = models.ManyToManyField(Tag, through='SiteTag')
class SiteTag(models.Model):
site = models.ForeignKey(Site, on_delete=models.RESTRICT)
tag = models.ForeignKey(Tag, on_delete=models.RESTRICT)
Where a site can have multiple tags using explicit Many-to-Many relationship. When I filter site with a specific tag in the following query other tags are filtered out where I mean give me sites with this tags and show all tags those sites have:
Site.objects.filter(tags__key__in=['type-1', 'type-2'])\
.annotate(tags=ArrayAgg("tags__key", distinct=True, filter=Q(tags__isnull=False)))
Then it indeed retrieve sites with either type-1
or type-2
but if a selected site has the type-3
tag I also want to collect it in the ArrayAgg
aggregation. Unfortunetly with this query I will only have ["type-1", "type-2"]
in annotated tags field instead of ["type-1", "type-2", "type-3"]
.
How can I filter sites using this criterion and still have all tags collected in the annotate section.
Upvotes: 0
Views: 46
Reputation: 11052
Sometimes writing the question is enough to find out the solution, the key was to call all
after annotate
and before filter
.
Site.objects.annotate(
tags=ArrayAgg("tags__key", distinct=True, filter=Q(tags__isnull=False)
).all().filter(tags__key__in=['type-1', 'type-2'])
This query filters as expected and returns all aggregated tags.
Upvotes: 0