Search code examples
django-rest-frameworkdjango-serializer

Get rid of nested serialized data and make custom data format


I have Serializer data format like this, where task is ForeignKey to another model:

class OfferSerializer(serializers.ModelSerializer):
    class Meta:
        model = Offer
        fields = ("id", "task", "type")
        read_only_fields = ("id", "task", "type")
{
  "id": 1,
  "task": 1,
  "type": "offer"
},
{
  "id": 2,
  "task": 2,
  "type": "counter_offer"
}

Code from my views.py

...
offers_queryset = Offer.objects.all()
serializer = self.get_serializer(offers_queryset, many=True)
return Response(serializer.data)

I need to expand Task for some information and get rid of nesting. Right now I can only achieve this type:

class TasksOffersSerializer(serializers.ModelSerializer):
    task = TaskSerializer(read_only=True)

    class Meta:
        model = Offer
        fields = ("id", "task", "type")
        read_only_fields = ("id", "task", "type")
{
  "id": 1,
  "task": {
            "id": 1,
            "task_fields": "values"
          },
  "type": "offer"
},
{
  "id": 2,
  "task": {
            "id": 2,
            "task_fields": "values"
          },
  "type": "counter_offer"
},

My goal is to retrieve data in format like this, without nesting data:

[
  {
    "offer": {
               "id": 1,
               "type": "offer"
             }
    "task": {
              "id": 1,
              "task_fields": "values"
            }
  },
  {
    "offer": {
               "id": 2,
               "type": "counter_offer"
             }
    "task": {
              "id": 2,
              "task_fields": "values"
            }
  },
]

Is it possible to do with DjangoORM or should I manipulate querysets like lists and dictionaries with Python somehow?

Edit: My models (simplified)

class Task(models.Model):
    description = models.CharField(max_length=128)
    ...

class Offer(models.Model):
    task = models.ForeignKey("task.Task", on_delete=models.CASCADE)
    price = models.IntegerField()
    ...

The best I want to achieve is

class TasksOffersSerializer(serializers.Serializer):
    task = TaskSerializer()
    offer = OfferSerializer()

Solution

  • You can use a custom serializer in django.In the views you can retrieve the response from the 'data' key.

    
    class TasksOfferSerializer(serializers.Serializer):
    
        data = serializers.SerializerMethodField()
    
        def get_data(self, obj):
            return response = {
                "offer": {
                        "id": obj.id,
                        "type": obj.type
                    }
                "task":{
                        "id":obj.task.id,
                        "task_name": obj.task.name
                    }    
                }