如何从rest_framework序列化器获得漂亮的输出

时间:2014-04-21 10:09:19

标签: json django serialization django-rest-framework

我正在使用django rest_gramework序列化程序来转储我的对象的json:

response = InstallSerializer(Install.objects.all(), many=True).data
return StreamingHttpResponse(response, content_type='application/json')

,其中

class InstallSerializer(serializers.ModelSerializer):
    modules = ModuleSerializer(many=True)

    class Meta:
        model = Install
        fields = ('id', 'install_name', 'modules')

然而,这个输出不是“可读的”......它全部都在一行上。

{'id': 1, 'install_name': u'Combat Mission Battle For Normandy', 'modules': [{'id': 1, 'name': u'Combat Mission Battle For Normandy', 'versions': [{'id': 1, 'name': u'1.00-Mac', 'brzs': [1, 2, 3]}]}]}

有没有办法让串行器更好地格式化输出?

(用于调试的外观检查)

注意:我刚刚了解到我输出上面显示的序列化表单的方法甚至没有生成有效的json,尽管它看起来很相似。您必须执行下面接受的答案中显示的json.dump步骤才能获得有效的json,并且作为奖励它也非常好。

6 个答案:

答案 0 :(得分:9)

当您使用rest_framework时,您不应该自己使用json.dumps,因为渲染器会为您完成这项工作。您看到的数据是python字典,它是序列化程序的输出。它不会被DRF呈现,因为您正在返回Django StreamingHttpResponse。需要渲染此数据才能获得JSON。 您是否有理由绕过rest_framework渲染?

否则,这是你的处理程序:

return Response(InstallSerializer(Install.objects.all(), many=True).data)

Responserest_framework.response.Response的位置。

如果您的客户端需要漂亮的json:rest_framework JSONRenderer支持indent标头的Accept参数(请参阅the docs)。

所以当你的客户发送:

Accept: application/json; indent=4

您的JSON将缩进。

答案 1 :(得分:8)

除了Denis Cornehl的回答之外,您还可以强制使用精美打印输出,而客户端不会在其Accept:标题中指定此类输出。相反,当您像这样调用renderer_context时,请在render()参数中指定它:

content = JSONRenderer().render(data, renderer_context={'indent':4})

通过调整Django Rest Framework's tutorial中的示例,您可以漂亮地打印所有JSON序列化对象:

class JSONResponse(HttpResponse):
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data, renderer_context={'indent':4})
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

答案 2 :(得分:7)

我是这样做的:

class PrettyJsonRenderer(JSONRenderer):    
    def get_indent(self, accepted_media_type, renderer_context):
        return 2

然后在您网站的PrettyJsonRenderer文件中指定settings.py

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'myapp.util.PrettyJsonRenderer',
    )
}

答案 3 :(得分:2)

使用下面的行

import json
return StreamingHttpResponse(json.dumps(response, sort_keys=True, indent=4, separators=(',', ': ')),   mimetype='application/json')

答案 4 :(得分:0)

不确定这是否最适合您的用例,但我发现当我在ReturnDict对象的dict()上调用pprint时,我得到更多的可读结果:

ipdb> type(self.response.body)
<class 'rest_framework.utils.serializer_helpers.ReturnDict'>
ipdb> dict(self.response.body)
{'status': 'Open', ..., 'voucher_discounts': []}  # all on one line
ipdb> pprint(dict(self.response.body))
{'currency': u'EUR',
 'id': 1,
 'lines': [OrderedDict([('url', u'http://testserver/api/baskets/1/lines/1/'), ...]), ...],
 ...
 'voucher_discounts': []}

仍然不会格式化为&#39;行&#39;中的词组列表。虽然。

答案 5 :(得分:0)

您可以在视图中添加headers={'indent': ' '}作为响应来执行此操作。试试这个:

class JSONListView(ReadOnlyModelViewSet):
    queryset = YourModel.objects.all()
    serializer_class = YourSerializer

    def get_renderers(self):
        return [JSONRenderer()]

    def get_renderer_context(self):
        serializer = self.get_serializer(self.get_queryset(), many=True)
        response = Response(data=serializer.data, headers={'indent': '    '})
        return response