Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rest_framework: child object count in serializer

I need to count the number of children an object has and return this value in my API via the object serializer. I also need to count a subset of these children objects.

I have a Task object with children Asignees. In my API when I query the tasks I want to have the following data set returned:

[
    { label: "Cross the bridge",
      count_assigned: 5,
      count_completed: 3 },
    { label: "Build a fire",
      count_assigned: 5,
      count_completed: 2 }
]

How would I do this? I have found the .annotate() method but that result is not available in the serializer class.

models.py

class Task(models.Model):
    label         = models.CharField(max_length=255,null=False,blank=False)

class Assignee(models.model):
    task         = models.ForeignKey(Task, related_name='assignees', on_delete=models.CASCADE, blank=True, null=True) 
    person       = models.ForeignKey(Person, on_delete=models.CASCADE, blank=True, null=True)
    completed    = models.DateTimeField(null=True,blank=True)

serializers.py

from rest_framework import serializers

from .models import Task, Assignee
from people.serializers import PersonSerializer

class AssigneeSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()
    person = PersonSerializer(read_only=True)

    class Meta:
        model = Assignee

        fields = ('id','task','person','completed')
        read_only_fields = ['id']


class TaskSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = Task

        fields = ('id', 'label')
        read_only_fields = ['id']
like image 358
Codewise Avatar asked Sep 20 '17 15:09

Codewise


1 Answers

The proposed way

class TaskSerializer(serializers.ModelSerializer):
     id = serializers.ReadOnlyField()
     count_assigned = serializers.SerializerMethodField()
     count_completed = serializers.SerializerMethodField()

     class Meta:
         model = Task
         fields = ('id', 'label', 'count_assigned', 'count_completed')

    def get_count_assigned(self, obj):
        return obj.assignees.count()

    def get_count_completed(self, obj):
        return obj.assignees.exclude(completed__isnull=True).count()

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

like image 107
Iyvin Jose Avatar answered Sep 30 '22 09:09

Iyvin Jose