I've been at this for a while now. Any guidance is appreciated.
I have to implement a django rest_framework with JSON API output with pagination. Seems simple enough. I've done it many times before. But this time I don't have an underlying model wo work from.
My data comes from a third-party SDK which just returns a list of dictionaries. It's complex data with nested lists and such, but in the end it's just a list of dicts.
I got to the point where I'm able to display my data and even paginate it (sort of). But there are no "links" nor are there any "next", "prev", or "count" fields in my output.
I'm posting my snippets here changing the name to not expose the 3rd party provider.
Here is the serializer I have so far:
from rest_framework import serializers
class MySerializer(serializers.Serializer):
def to_representation(self, instance):
return instance
This is my view:
class MyViewSet(ViewSet):
serializer_class = serializers.MySerializer
queryset = sdk.get_all_the_things()
def list(self, request):
page = self.paginate_queryset(self.queryset)
return Response(page)
sdk.get_all_the_things() returns a list of dicts, similar to:
[{
"foo": "something",
"bar": "more stuff",
...
},
{
...
},
and so on....
]
I have no control over this input directly and the underlying dict structure could change at any time. Again the format of the dict isn't all that critical.
This seems to work (sort of) but as stated before, pagination links are missing. I think this is because of self.paginate_queryset(self.queryset). I can't seem to find any other reason nor does any amount off googling help me.
I've tried going down the route of using the serializers
serializer = serializers.MySerializer(self.queryset, many=True)
return Response(serializer.data)
This just gives me the dreaded 'dict' objects has no attribure 'pk'. I'm guessing because it is expecting a model object.
I'm at my wits end here so again any guidance would be really appreciated.
Ok. Much lost sleep but I finally figured it out. Turns out the issues wasn't with DRF itself, but a limitation in the django-rest-framework-json-api package. Everything started working once I disabled the json_api renderer. But JSON:API is in the requirement so I had to forge on....
I managed to get this working by creating a dummy object and populating a list with those objects. I'm posting my solution here in case any one else comes across this and needs a solution:
First, I create a dummy object:
class DummyObject(object):
def __init__(self, **kwargs):
for field in ('id', 'data'):
setattr(self, field, kwargs.get(field, None))
Then had to manipulate the list of dicts. This is somewhat ugly code but worked:
resultset = sdk.get_all_the_things()
index = 0
instances = []
for instance in resultset:
temp_obj = DummyObject()
temp_obj.data = instance
temp_obj.pk = index
instances.append(temp_obj)
index += 0
return instances
Then Changed my serializer to serialize the object data:
from . import DummyObject
class MySerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
data = serializers.DictField()
def create(self, validated_data):
return DummyObject(pk=None, **validated_data)
class Meta:
resource_name = 'instances'
This converted each dict in my list to an object, Which I was then able to add my 'pk' attribute to.