'How to add an extra dictionary to ModelViewset response?
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",
Solution 1:[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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Pranav Choudhary |
