Stevy
Stevy

Reputation: 3387

Django serializer output as part of JSON object

Context

I have 2 models: Customer & DeviceGroup.

Currently I have an API endpoint /api/v1/device-groups/?customer_uuid=<customer_uuid> which returns the DeviceGroups that are related to the given Customer like this:

[
    {
        "group_uuid": "c61361ac-0826-41bb-825a-8aa8e014ae0c",
        "device_group_name": "Default",
        "color": "0a2f45",
        "is_default": true
    },
    {
        "group_uuid": "1a86e8e4-b41b-4f33-aefb-ce984ef96144",
        "device_group_name": "Testgroup",
        "color": "123456",
        "is_default": false
    }
] 

Goal

I want the array of DeviceGroups be part of an object like this:

"device_groups": 
[
    {
        "group_uuid": "c61361ac-0826-41bb-825a-8aa8e014ae0c",
        "device_group_name": "Default",
        "color": "0a2f45",
        "is_default": true
    },
    {
        "group_uuid": "1a86e8e4-b41b-4f33-aefb-ce984ef96144",
        "device_group_name": "Testgroup",
        "color": "123456",
        "is_default": false
    }
] 

Models

# models.py

class Customer(models.Model):
    customer_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
    customer_name = models.CharField(max_length=128, unique=True)


class DeviceGroup(models.Model):
    group_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
    customer_uuid = models.ForeignKey(Customer, on_delete=models.DO_NOTHING)
    device_group_name = models.CharField(max_length=20)
    color = models.CharField(max_length=10)
    is_default = models.BooleanField(default=False)

Serializer

# serializers.py

class DeviceGroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = DeviceGroup
        fields = ('group_uuid', 'device_group_name', 'color', 'is_default')

View

# views.py

class DeviceGroupCustomerViewSet(viewsets.ModelViewSet):
    serializer_class = DeviceGroupSerializer

    def get_queryset(self):
        return DeviceGroup.objects.filter(customer_uuid=self.request.GET['customer_uuid'])

I tried creating a new serializer but it did not solve my problem:

class TestSerializer(serializers.ModelSerializer):
    device_groups = DeviceGroupSerializer(many=True, read_only=True)

    class Meta:
        model = DeviceGroup
        fields = ('device_groups', 'group_uuid', 'device_group_name', 'color', 'is_default')

What do I need to change in order to get my desired output?

Upvotes: 1

Views: 665

Answers (3)

Ken4scholars
Ken4scholars

Reputation: 6296

To achieve this fairly easily without loosing the pagination, I would do this:

from rest_framework.pagination import PageNumberPagination 

class DeviceGroupPagination(PageNumberPagination):

    def get_paginated_response(self, data):
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('device_groups', data)
        ]))

Then in the views

class DeviceGroupCustomerViewSet(viewsets.ModelViewSet):
    serializer_class = DeviceGroupSerializer
    pagination_class = DeviceGroupPagination
    ...

So now, in place of results, you will have device_groups

Upvotes: 1

Shihabudheen K M
Shihabudheen K M

Reputation: 1397

you can update your views like

def list(self, request):
    queryset = DeviceGroup.objects.filter(customer_uuid=self.request.GET['customer_uuid'])
    serializer = UserSerializer(queryset, many=True)
    return Response({'device_groups': serializer.data})

this will get the desired output..

Upvotes: 3

crax
crax

Reputation: 556

Just modify your new serializer named TestSerializer in the following way.

class TestSerializer(serializers.Serializer):
    device_groups = serializers.SerializerMethodField(read_only=True)

    def get_device_groups(self, model):
        return DeviceGroupSerializer(model).data

The response will be a paginated response. If you want to disable it just mention pagination_class as None in your ModelViewset class.

Upvotes: 3

Related Questions