How to customize the response of Django REST Framework GET request

djangodjango-rest-framework

I have a model Foo which I use as the model for my vanilla DRF serializer.

models.py

class Foo(models.Model):
    name = models.CharField(max_length=20)
    description = models.TextField()
    is_public = models.BooleanField(default=False)

serializers.py

class FooSerializer(serializers.ModelSerializer):
    class Meta:
        model = Foo

views.py

class FooRetrieveAPIView(RetrieveAPIView):
    queryset = Foo.objects.all()
    serializer_class = FooSerializer

Now the result of this endpoint is being used by front-end code, which is then the basis on how the next page to show is identified. Anyway, I need to change the structure of the results returned for both status 200 (existing record) and 404 (non-existent record).

Actual result (from vanilla DRF):

$ curl localhost:8000/foo/1/  # existing record
{"id": 1, "name": "foo", "description": "foo description", is_public=false}

$ curl localhost:8000/foo/2/  # non-existent record
{"detail": "Not found."}

How I want the results to be:

$ curl localhost:8000/foo/1/
{"error": "", "foo": {"id": 1, "name": "foo", "description": "foo description", is_public=false}}

$ curl localhost:8000/foo/2/
{"error": "Some custom error message", "foo": null}

I've mostly used vanilla DRF so things are pretty straightforward so this customization of the response structure is a bit new to me.

Django version used: 1.9.9

DRF version used: 3.3.x

Best Answer

You can rewrite retrieve method in your view in order to update your serializer response data

class FooRetrieveAPIView(RetrieveAPIView):
    queryset = Foo.objects.all()
    serializer_class = FooSerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = serializer.data
        # here you can manipulate your data response
        return Response(data)
Related Topic