Gocht
Gocht

Reputation: 10256

DRF - Format Serializer's output from QuerySet

I am working with Django Rest Framework by firt time and now I'm trying to get an output like this:

{
  "qty": 5,
  "total": 20,
  "items": [
     {
       "id": 1,
       "name": "name_1"
     },
     {
       "id": 2,
       "name": "name_2"
     }
  ]
}

from a Serializer. The result data in output above, came from a queryset. I'd like to work with the queryset inside the serializer class. I've not been able to get results as I want without makeing queries inside the serializer:

class ResSerializer(serializers.Serializer):

    qty = serializers.SerializerMethodField()
    items = serializers.SerializerMethodField()
    total = serializers.SerializerMethodField()

    def get_qty(self, obj):
        try:
            return Model.objects.filter(...)\
                                .aggregate(qty=Sum('job__long'))\
                                .get('qty')
        except KeyError:
            return 0

    def get_items(self, obj):
        print 'testing'

    def get_total(self, obj):
        return 0

    class Meta:
        fields = ('qty', 'items', 'total')

I'm calling Serializer like this:

queryset = Model.objects.filter(...)
serialized = ResSerializer(queryset, many=False, context={'current_user': request.user})

But this is not working as I want. Any sugestion? Thanks.

UPDATE

This is the model I query to:

class Intermediate(models.Model):

    partner = models.ForeignKey('partner.Partner')
    job = models.ForeignKey(Job)
    joined_at = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    status = models.SmallIntegerField(default=STATUS_ACCEPTED)
    reason_index = models.SmallIntegerField('Cancel reason', default=REASON_3)
    start_time = models.TimeField(null=True)
    end_time = models.TimeField(null=True)
    start_date = models.DateField(null=True)
    end_date = models.DateField(null=True)

And here's the view:

class ResView(CustomAPIView):

    authentication_classes = (CustomTokenAuthentication, )
    # permission_classes = (PartnerAuthenticatedOnly, )  # Uncomment this on server

    def post(self, request, *args, **kwargs):
        try:
            queryset = JobPartner.objects.filter(...)
            serialized = ResSerializer(queryset, many=False, context={'current_user': request.user})
            response_success_object(self.response_dic, serialized.data)
            return Response(self.response_dic)

        except Exception, e:
            print e

Upvotes: 1

Views: 2932

Answers (1)

Rahul Gupta
Rahul Gupta

Reputation: 47856

To get the items representation, you can use ItemsSerializer which will give the serialized data having id and name.

class ItemsSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel # specify your model
        fields = ('id', 'name') # return these 2 fields in the representation

This serializer when dealing with multiple instances will return the serialized data in below fashion.

[
     {
       "id": 1,
       "name": "name_1"
     },
     {
       "id": 2,
       "name": "name_2"
     }
  ]

Now, the qty and total fields depends on the queryset and not a particular object of the queryset, it would be better if you compute them separately in your view. Then create a dictionary containing the fields items, qty and total and return it as the response.

class ResView(CustomAPIView):

    authentication_classes = (CustomTokenAuthentication, )
    # permission_classes = (PartnerAuthenticatedOnly, )  # Uncomment this on server

    def post(self, request, *args, **kwargs):
        try:
            queryset = JobPartner.objects.filter(...)
            qty = self.get_qty() # compute the value of qty
            total = self.get_total() # compute the value of total
            items_serializer = ItemsSerializer(queryset, many=True) 
            items = items_serializer.data # compute the value of items
            return_dict = { # prepare response data
                'qty' : qty,
                'total': total,
                'items': items 
            }
            return Response(return_dict) # return the response

        except Exception, e:
            print e

Upvotes: 1

Related Questions