2

I want to filter the results before counting. In below code, I am counting the total number of workers for each Ticket Counter.

class TicketCounterList(ListAPIView):
    queryset = TicketCounter.objects.filter(ticket_counter_is_deleted=False)
            .annotate(num_workers=Count('workers'))
    serializer_class = TicketCounterSerializer

workers in the above code is the related_name from another model ( WorkerToTicketCounter model). What I want to do is, I want to be able to filter workers with a condition is_deleted= True rather than counting all workers. Is it possible? I am using Django 1.11.13

Is there anything like below

queryset = TicketCounter.objects.filter(ticket_counter_is_deleted=False)
            .annotate(num_workers=Count('workers',filter="xxxx"))

get it? I want to filter the workers.

EDIT: My Models:

class TicketCounter(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    ticket_counter_name = models.CharField(max_length=100, default="")
    ticket_counter_description = models.CharField(max_length=1500, default="")
    ticket_counter_address = models.CharField(max_length=1500, default="")


class WorkerToTicketCounter(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    ticket_counter = models.ForeignKey(TicketCounter,related_name="workers")
    worker = models.ForeignKey(User,related_name='worker_for_ticket_counter')

My Serializer:

class TicketCounterSerializer(serializers.ModelSerializer):
    num_workers = serializers.IntegerField()
    class Meta:
        model = TicketCounter
        fields = (
            'ticket_counter_name',
            'ticket_counter_description',
            'ticket_counter_address',
            'num_workers',
        )
Naroju
  • 2,637
  • 4
  • 25
  • 44
  • Kindly add your models to be more clear. – Rk.. Aug 31 '18 at 15:32
  • Similar https://stackoverflow.com/questions/33775011/how-to-annotate-count-with-a-condition-in-a-django-queryset and https://stackoverflow.com/questions/30752268/how-to-filter-objects-for-count-annotation-in-django – Risadinha Aug 31 '18 at 15:42
  • Possible duplicate of [How to filter objects for count annotation in Django?](https://stackoverflow.com/questions/30752268/how-to-filter-objects-for-count-annotation-in-django) – Risadinha Aug 31 '18 at 15:45

1 Answers1

2

Since , you can do filtering in the Count, but this will not help us here.

What we however can do is sum up the workers__is_deleted, or its negation. For example if we want to return the number of workers that are not deleted:

from django.db.models import F, IntegerField, Sum, Value
from django.db.models.functions import Coalesce

class TicketCounterList(ListAPIView):
    queryset = TicketCounter.objects.filter(
        ticket_counter_is_deleted=False
    ).annotate(
        num_workers=Cast(
            Coalesce(Sum(Value(1) - F('workers__is_deleted')), Value(0)),
            IntegerField()
        )
    )
    serializer_class = TicketCounterSerializer

Or if you want to count the deleted workers:

from django.db.models import F, IntegerField, Sum, Value
from django.db.models.functions import Coalesce

class TicketCounterList(ListAPIView):
    queryset = TicketCounter.objects.filter(
        ticket_counter_is_deleted=False
    ).annotate(
        num_workers=Cast(
            Coalesce(Sum(F('workers__is_deleted')), Value(0)),
            IntegerField()
        )
    )
    serializer_class = TicketCounterSerializer
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555