0

using the model

class Sim(modesl.Model):
    iccid = models.CharField(max_length=64)
    carrier = models.CharField(max_length=50)
    status = models.CharField(max_length=100)
    
    class Meta(object):
       app_label = "app"
       verbose_name = "Sim"
    class JSONAPIMeta:
       resource_name = "sim"
       external_field = "id"

using the view :

class SimView(viewsets.ModelViewSet):
    
    queryset = Sim.objects.all()
    serializer_class = SimSerializer

using serializer:

class SimSerializer(serializers.ModelSerializer):

    class Meta:
        model = Sim
        fields = "__all__"

for /get/

{
    "links": {
        "first": "some link",
        "last": "some link"
        "next": null,
        "prev": null
    },
    "data": [
        {
            "type": "sim",
            "id": "1",
            "attributes": {
                "carrier": "Vodaphone",
                "iccid": "12345678912345678912",
                "status": "UnManaged",

            }
        }
    ],
    "meta": {
        "pagination": {
            "count": 1,
            "limit": 20,
            "offset": 0
        }
    }
}

Now I want a dictionary "license_info" to be sent in the response which should appear only once in response, so the response may look like:

{
    "links": {
        "first": "some link",
        "last": "some link"
        "next": null,
        "prev": null
    },
    "data": [
        {
            "type": "sim",
            "id": "1",
            "attributes": {
                "carrier": "Vodaphone",
                "iccid": "12345678912345678912",
                "status": "UnManaged",

            }
        }
      #Either add here 
      {
       "license_info":"some value"   
      }
    ],
    "meta": {
        "pagination": {
            "count": 1,
            "limit": 20,
            "offset": 0
        }
    }
 #Or Add here 
  "license_info":{
     "some key value pairs"
  }

}

I tried to make license_info as property but this was getting repeated for each instance.

Another method that I tried was to override list method

def list(self, request, *args, **kwargs):

        instance = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(instance)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
        else:
            serializer = self.get_serializer(instance, many=True)

        serializer_data = serializer.data # get the default serialized data 
        serializer_data.append({"license_info": "some value"})
        return self.get_paginated_response(serializer.data) if page else Response(serializer_data)

But this was giving following error :

"/home/pranav/Desktop/cp_projects/connector/venv/lib/python3.7/site- 
packages/rest_framework_json_api/renderers.py\", line 589, in render\n    
resource_instance = serializer.instance[position]  # Get current instance\nIndexError: 
list index out of range", "status_code": 500, "request": "<WSGIRequest: GET 
'/api/v1/sim'>", "level": "ERROR"} 

I have also tried :

def list(self, request, *args, **kwargs):
    
            instance = self.filter_queryset(self.get_queryset())
            page = self.paginate_queryset(instance)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
            else:
                serializer = self.get_serializer(instance, many=True)
    
            newdict = []
            newdict.append(serializer.data)
            newdict.append({"license_info": "some value"})
            return Response(newdict, status=status.HTTP_201_CREATED)

But using this I was getting response payload without "links" and "meta" key-value.

I am using following setting for rest_framework:

"DEFAULT_PAGINATION_CLASS": "rest_framework_json_api.pagination.JsonApiLimitOffsetPagination",
    "PAGE_SIZE": env["max_page_size"],
    "DEFAULT_PARSER_CLASSES": ("rest_framework_json_api.parsers.JSONParser",),
    "DEFAULT_RENDERER_CLASSES": rest_framework_json_api.renderers.JSONRenderer,
    "DEFAULT_METADATA_CLASS": "rest_framework_json_api.metadata.JSONAPIMetadata",
Pranav Choudhary
  • 2,726
  • 3
  • 18
  • 38

1 Answers1

1

To add an extra dictionary to the response in the given way you can create a custom pagination class and override the get_paginated_response that will return the response in the required way and then in list method you can dynamically change the value of that extra dictionary.

class CustomLimitOffsetPagination(JsonApiLimitOffsetPagination):
    
    def get_paginated_response(self, data):
        return Response(
            {
                "results": data,
                "meta": {
                    "pagination": OrderedDict(
                        [
                            ("count", self.count),
                            ("limit", self.limit),
                            ("offset", self.offset),
                        ]
                    )
                },
                "links": OrderedDict(
                    [
                        ("first", self.get_first_link()),
                        ("last", self.get_last_link()),
                        ("next", self.get_next_link()),
                        ("prev", self.get_previous_link()),
                    ]
                ),
              #Extra dictionary 
              "license_info":OrderedDict(),

            }
        )

Add this paginate class for you rest_framwork in settings

"DEFAULT_PAGINATION_CLASS": "path to your CustomLimitOffsetPagination",

Now to add value to "license_info" you have to override list method in views

def list(self,request,*args,**kwargs):
   instance = self.filter_queryset(self.get_queryset())
   page = self.paginate_queryset(instance)
   response = None
   
   if page is not None:
     serializer = self.get_serializer(page,many=True)
     response = self.get_paginated_response(serializer.data)
     response.data["license_info"] = OrderedDict(
                        [
                            ("key", "value"),
                        ]
                    )
   else:
     serializer = self.get_serializer(instance,many=True)
     response_data = []
     response_data.extend(serializer.data)
     response_data.append({"license_info":"some value"})
     response = Response(response_data)
   
   return response
Pranav Choudhary
  • 2,726
  • 3
  • 18
  • 38