2014-04-21 6 views
9

Używam django rest_gramework serializatora, aby zrzucić json moich obiektów:Jak uzyskać ładny wyjście z rest_framework serializatora

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

gdzie

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

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

itp

jednak to wyjście nie jest "czytelne" ... pojawia się w jednym wierszu.

{'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]}]}]} 

Czy istnieje sposób, aby zapytać serializera, aby lepiej sformatować wynik?

(Dla kontroli wzrokowej debugowania)

Uwaga: Właśnie dowiedziałem się, że moje podejście do wyprowadzania odcinkach postać pokazaną powyżej nawet nie produkują ważny json, choć wygląda podobnie. Musisz wykonać krok json.dump pokazany w zaakceptowanej odpowiedzi poniżej, aby uzyskać poprawny json, a jako bonus jest również całkiem niezły.

+1

Zawsze możesz użyć interfejsu API do przeglądania http://www.django-rest-framework.org/topics/browsable-api#urls do debugowania. Drukuje JSON w czytelnym formacie. – fasouto

Odpowiedz

7

Kiedy używasz rest_framework nie należy używać json.dumps siebie, ponieważ renderers zrobić to za Ciebie. Dane, które widzisz, to słownik Pythona, który jest wynikiem działania serializera. To nie jest renderowane przez DRF, ponieważ zwracasz Django StreamingHttpResponse. Te dane muszą być renderowane, aby uzyskać JSON. Czy jest jakiś powód, dla którego pomijasz renderowanie reszty_ramki?

W przeciwnym razie, jest to Handler:

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

Gdzie Response jest rest_framework.response.Response.

Jeśli klient potrzebuje ładny json: The rest_framework JSONRenderer wspiera indent argument dla nagłówka Accept (patrz the docs).

Więc gdy klient wysyła:

Accept: application/json; indent=4 

Twój JSON będzie wcięte.

+0

Dzięki, muszę to zaabsorbować! – GreenAsJade

+0

Hmm - próbowałem to zaimplementować, ale otrzymuję "accept_renderer nie ustawiony na Response". Wstawiłem REST_FRAMEWORK = {DEFAULT_RENDERER_CLASSES ": (" rest_framework.renderers.JSONRenderer ")} bez skutku .... – GreenAsJade

+0

Znalazłem, że muszę dodać adnotację @api_view (['GET', 'POST']) do mojego handler'a . – GreenAsJade

2

użycie poniżej linii

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

Niezły! Wydaje się to również rozwiązywać problem, że surowe wyjście z serializera ('response') nie było faktycznie poprawne json, które właśnie odkrywałem, gdy badałem opcje faouto, które wskazywały na mnie. – GreenAsJade

7

Oprócz odpowiedzi Denisa Cornehla, można również wymusić drukowanie na dość wydrukowanym obrazie bez podania przez klienta takich informacji w nagłówku Accept:.Zamiast tego, można określić ją w parametrze renderer_context kiedy zadzwonić render() takiego:

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

przez szczypanie przykład z Django Rest Framework's tutorial, można całkiem-print wszystkie serializowane obiekty 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) 
3

zrobiłem z tego:

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

a następnie określ PrettyJsonRenderer w twojej witryny settings.py pliku:

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

Nie wiem, czy to służy przypadku użycia najlepiej, ale okazało się, że dostać więcej readble rezultat gdy zgłoszę pprint na dict() obiektu ReturnDict:

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': []} 

Wciąż ją nie sformatuje jednak listy dyktorów w "liniach".

Powiązane problemy