【问题标题】:How to get pretty output from rest_framework serializer如何从 rest_framework 序列化程序获得漂亮的输出
【发布时间】:2014-06-05 09:19:39
【问题描述】:

我正在使用 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,而且它也很漂亮。

【问题讨论】:

标签: json django serialization django-rest-framework


【解决方案1】:

我这样做了:

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

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

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

【讨论】:

  • 谢谢!我刚刚将 get_indent() 方法添加到我们现有的自定义 JSON Renderer 类中,它运行良好。
  • 谢谢,重写渲染器的想法是关键
【解决方案2】:

当您使用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 将被缩进。

【讨论】:

  • 谢谢,我需要吸收这个!
  • 嗯 - 我已经尝试实现这一点,但我得到“accepted_renderer not set on Response”。我把 REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ('rest_framework.renderers.JSONRenderer')} 无济于事....
  • 我发现我需要在我的处理程序中添加 @api_view(['GET', 'POST']) 注释。
【解决方案3】:

除了 Denis Cornehl 的回答之外,您还可以强制打印漂亮的输出,而无需客户端在其 Accept: 标头中指定。相反,当您像这样调用render() 时,您在renderer_context 参数中指定它:

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)

【讨论】:

    【解决方案4】:

    使用下面的行

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

    【讨论】:

    • 不错的一个!这似乎也解决了序列化程序 (response) 的原始输出实际上不是有效的 json 的问题,这是我在探索 faouto 指出的选项时才发现的。
    【解决方案5】:

    不确定这是否最适合您的用例,但我发现当我在 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': []}
    

    但它仍然不会格式化为“行”中的字典列表。

    【讨论】:

      【解决方案6】:

      您可以在您的视图中添加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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-09
        • 1970-01-01
        • 2022-11-18
        相关资源
        最近更新 更多