如何在Django Rest Framework中创建自定义JSON有效负载结构?

时间:2016-05-16 19:30:19

标签: django rest django-models django-rest-framework

我正在创建一个API,需要所有JSON响应的自定义结构。

{
    code: 200,
    payload: [
        {...},
        {...},
        {...}
    ]
}

payload包含查询返回的所有项目。

我已经创建了一个扩展Renderer的自定义JSONRenderer,但为了访问响应代码,我需要访问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)

这是进行此类包装的正确位置还是应该在ViewSet等其他地方进行,或者通过扩展Response对象?

1 个答案:

答案 0 :(得分:5)

这是包装响应的正确位置,因为在中间件中执行错误检查后会呈现响应。

在视图中执行此操作可能会导致意外结果,例如,code参数无法正确捕获序列化错误,并将其包装在自定义序列化程序中将无法访问响应对象。此外,您可能希望在响应中包含身份验证或限制错误。

请注意,发生的任何分页也将包含在您的payload参数中:

{
    "code":200,
    "payload": {
        "count": 20,
        "next": 2,
        "previous": 0,
        "results": [
            ...
        ]
    }
}

对此的一个解决方案是使用HTTP标头实现分页。

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)