While constructing a complexe QuerySet
with several annotations, I ran into an issue that I could reproduce with the following simple setup.
Here are th
Based on the excellent answer from @rktavi, I created two helpers classes that simplify the Subquery
/Count
and Subquery
/Sum
patterns:
class SubqueryCount(Subquery):
template = "(SELECT count(*) FROM (%(subquery)s) _count)"
output_field = PositiveIntegerField()
class SubquerySum(Subquery):
template = '(SELECT sum(_sum."%(column)s") FROM (%(subquery)s) _sum)'
def __init__(self, queryset, column, output_field=None, **extra):
if output_field is None:
output_field = queryset.model._meta.get_field(column)
super().__init__(queryset, output_field, column=column, **extra)
One can use these helpers like so:
from django.db.models import OuterRef
weapons = Weapon.objects.filter(unit__player_id=OuterRef('id'))
units = Unit.objects.filter(player_id=OuterRef('id'))
qs = Player.objects.annotate(weapon_count=SubqueryCount(weapons),
rarity_sum=SubquerySum(units, 'rarity'))