Home > Software engineering >  How do I "flatten" a nested serializer in DRF?
How do I "flatten" a nested serializer in DRF?

Time:01-08

We have a nested serializer that we would like to "flatten". But I'm not having much luck finding how to achieve this in the docs.

Here is the current output.

{
    "user_inventory": "UOHvaxFa11R5Z0bPYuihP0RKocn2",
    "quantity": 1,
    "player": {
        "card_id": "c69c0808328fdc3e3f3ee8b9b7d4a7f8",
        "game": "MLB The Show 22",
        "name": "Jesus Tinoco",
        "all_positions": [
            "CP"
        ]
    }
}

Here is what I'd like:

{
    "user_inventory": "UOHvaxFa11R5Z0bPYuihP0RKocn2",
    "quantity": 1,
    "card_id": "c69c0808328fdc3e3f3ee8b9b7d4a7f8",
    "game": "MLB The Show 22",
    "name": "Jesus Tinoco",
    "all_positions": [
        "CP"
    ]
}

Here is how the serializers are setup:

class PlayerProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = PlayerProfile
        fields = (
            'card_id',
            'game',
            'name',
            'all_positions',
        )

class UserInventoryItemSerializer(serializers.ModelSerializer):
    player = PlayerProfileSerializer()
    class Meta:
        model = UserInventoryItem
        fields = (
            'user_inventory',
            'quantity',
            'player',
        )

Here is the view:

class OwnedInventoryView(viewsets.ModelViewSet):
    serializer_class = UserInventoryItemSerializer
    filterset_class = UserInventoryItemFilter

    def get_queryset(self):
        order_by = self.request.query_params.get('order_by', '')

        if order_by:
            order_by_name = order_by.split(' ')[1]
            order_by_sign = order_by.split(' ')[0]
            order_by_sign = '' if order_by_sign == 'asc' else '-'
            return UserInventoryItem.objects.filter(user_inventory=self.kwargs['user_inventory_pk']).order_by(order_by_sign   order_by_name)

        return UserInventoryItem.objects.filter(user_inventory=self.kwargs['user_inventory_pk'])

CodePudding user response:

You can use .to_representation() method to alter data structure:

class UserInventoryItemSerializer(serializers.ModelSerializer):
    player = PlayerProfileSerializer()

    class Meta:
        model = UserInventoryItem
        fields = (
            'user_inventory',
            'quantity',
            'player',
        )

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        player = representation.pop('player')
        
        for key, value in player.items():
            representation[key] = value

        return representation
  • Related