Search code examples
djangodjango-annotate

Django annotate existance in related field


My models:

class Character(models.Model):
    name = models.CharField(max_length=100)

class Item(models.Model):
    name = models.CharField(max_length=100)

class Equipment(models.Model):
    owner = models.ForeignKey(Character, on_delete = models.CASCADE)
    item = models.ForeignKey(Item, on_delete = models.RESTRICT)

And now i need to annotate if items are in equipment:

 you = Character.objects.get(pk=1)
 items = Item.objects.all().annotate(ready=Value(True, output_field=models.BooleanField()), filter=Q(equipment__owner__in=you))

but something is wrong :

TypeError: 'Character' object is not iterable

Solution

  • You try to annotate and have this filter=Q(equipment__owner__in=you). The problem is you is an instance of Character not an iterable of characters so it should be filter=Q(equipment__owner=you). Still this is incorrect as you cannot filter inside an annotation this way.

    To annotate the existence of a related field use Exists() subqueries [Django docs]:

    from django.db.models import Exists, OuterRef
    
    you = Character.objects.get(pk=1)
    equipments = Equipment.objects.filter(item=OuterRef('pk'), owner=you)
    Item.objects.annotate(ready=Exists(equipments))