I'm creating an API that requires custom structure for all JSON responses.
{
code: 200,
payload: [
{...},
{...},
{...}
]
}
Where payload
contains all the items returned by the query.
I've created a custom Renderer
that extends JSONRenderer
but in order to access the response code I need to access the render_context
.
class VendorRenderer(JSONRenderer):
def render(self, data, accepted_media_type=None, render_context=None):
response = render_context['response']
data = {
'code': response.status_code,
'payload': data
}
return super(VendorRenderer, self).render(data, accepted_media_type, render_context)
Is this the right place to be doing this kind of wrapping or should it be taking place somewhere else like the ViewSet or by extending the Response object?
This is the correct place to wrap the response because responses are rendered after error checking is performed in the middleware.
Doing it in the view may cause unexpected results as, for example a serialization error won't be caught correctly by your code
parameter and wrapping it in a custom serializer won't have access to the response object. Also, you may want authentication or throttling errors to be wrapped in your response.
Be aware that any pagination that happens is also going to be wrapped in your payload
parameter:
{
"code":200,
"payload": {
"count": 20,
"next": 2,
"previous": 0,
"results": [
...
]
}
}
One solution to this is to implement pagination using HTTP headers.
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class StandardResultsSetHeaderPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 1000
def get_paginated_response(self, data):
headers = {
'X-Count': self.page.paginator.count,
'X-Next': self.get_next_link(),
'X-Previous': self.get_previous_link()
}
return Response(data, headers=headers)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With