Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

How to get complete list of related objects in Django-rest-Framework


I am trying to implement Nested serializer for the first time in django-rest-framework My requirement is i need the response data in below form :-

{
id: 0,
title: "Fresh",
data: [
    [{
            image: ".../assets/images/banana.jpeg",
            name: "Fruits",
            image_scaling: 2,
            API: "http://database_api"
        },
        {
            image: "../assets/images/banana.jpeg",
            name: "Vegetables",
            image_scaling: 2,
            API: "http://database_api"
        },
        {
            image: "../assets/images/banana.jpeg",
            name: "Exotic Vegetables",
            image_scaling: 2,
            API: "http://database_api"
        }
    ]
]

}

I am validating the token for the get api and listing the objects form DB. My current implementation of views.py is :-

class home(APIView):

 def get(self,request,format=None):

    header_token = request.META.get('HTTP_AUTHORIZATION', None)
    if header_token is not None:

        token = header_token
        access_token=token.split(' ')[1]
        print(access_token)
    
    if(validate_token(access_token) == None):
        raise NotFound('user does exist')
        

    queryset=Fresh.objects.all().select_related('data')
    print(queryset)
    serializer = FreshSerializer(queryset,many=True)
  
    return Response(serializer.data)

Serializer.py is :-

class DataSerializer(serializers.ModelSerializer):
   class Meta:
    model=data
    fields = ('name','image_scaling','image')

class FreshSerializer(serializers.ModelSerializer):
   data=DataSerializer(read_only=True, many=False)
   class Meta:
      model = Fresh
      fields = ('title','data')

models.py is :-

class data(models.Model):
  name=models.CharField(max_length=9,null=True)
  image_scaling=models.IntegerField(default=0,null=True)
  image=models.URLField(max_length = 200)
def __str__(self):
    return str(self.name)

class Fresh(models.Model):
   title=models.CharField(max_length=9)
   data=models.ForeignKey(data,on_delete=models.CASCADE,default=None, null=True)
def __str__(self):
    return str(self.title)+" " +str(self.data)

My current output is :-

[
{
    "title": "vegetable",
    "data": {
        "name": "vegetable",
        "image_scaling": 2,
        "image": "https......jpg"
    }
},
{
    "title": "exoticveg",
    "data": {
        "name": "exoticveg",
        "image_scaling": 2,
        "image": "https://.......jpg"
    }
} ]

I was trying to do by listapiview and modelviewset, but i am not able to get the desired output.I have seen similar queries in stack-overflow, but no solution seems to work for me. I am not getting list of objects of foreign key , am i doing something wrong in my model or running wrong query? I am really stuck at it. How shall i go about it. Please help!!!


Solution

  • i think you designed your models in wrong way:

    in your desired json, every fresh has many data, so you model should be like this:

    class data(models.Model):
      name=models.CharField(max_length=9, null=True)
      image_scaling=models.IntegerField(default=0, null=True)
      image=models.URLField(max_length=200)
      data=models.ForeignKey(
            Fresh, on_delete=models.CASCADE, related_name="fresh_data",
      )
    
    def __str__(self):
        return str(self.name)
    
    class Fresh(models.Model):
       title=models.CharField(max_length=9)
    
    def __str__(self):
        return str(self.title)
    

    and your serializer should be something like this:

    class DataSerializer(serializers.ModelSerializer):
       class Meta:
        model=data
        fields = ('name', 'image_scaling', 'image')
    
    class FreshSerializer(serializers.ModelSerializer):
       data = serializer.SerializerMethodField(read_only=True)
       class Meta:
          model = Fresh
          fields = ('id', 'title', 'data')
    
    
       def get_data(self, obj):
        return DataSerializer(obj.fresh_data, many=True).data