Reputation: 163
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
Upvotes: 4
Views: 9345
Reputation: 41
I had a similar problem and didn't want to create a custom exception handler as I wanted more control over defining error messages for api calls. After a bit of hand banging I used the following code in viewset to get custom error message while updating the record using partial_update.
def partial_update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
try:
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
headers = self.get_success_headers(serializer.data)
response = {"status": "True", "message": "", "data": serializer.data}
return Response(response, status=status.HTTP_201_CREATED, headers=headers)
except exception.Http404:
headers = ""
response = {"status": "False", "message": "Details not found", "data": ""}
return Response(response, status=status.HTTP_200_OK, headers=headers)
Upvotes: 2
Reputation: 22697
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)
Upvotes: 5