web-dev-qa-db-fra.com

Comment retourner un JSON personnalisé dans Django REST Framework

J'essaie de retourner un json personnalisé avec get_queryset mais toujours 404 error en réponse.

class TestViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Test.objects.all()
    serializer_class = TestSerializer

    def get_queryset(self):
        if self.request.method == "GET":
            content = {'user_count': '2'}
            return HttpResponse(json.dumps(content), content_type='application/json')

Si je supprime tout à partir de def j'obtiendrai une réponse correcte avec les données json standard. Qu'est ce que je fais mal?

35
Roberto

Si vous n'avez pas besoin d'un ModelViewSet et souhaitez simplement un JSON personnalisé sur une demande GET

Vous pouvez également utiliser un APIView , qui ne nécessite pas de modèle

class MyOwnView(APIView):
    def get(self, request):
        return Response({'some': 'data'})

et

urlpatterns = [
    url(r'^my-own-view/$', MyOwnView.as_view()),
]

Avec un ModelViewSet

Vous avez mis le JSON personnalisé dans get_queryset, c'est faux. Si vous souhaitez utiliser un ModelViewSet, cela devrait suffire en soi:

class TestViewSet(viewsets.ModelViewSet):
    queryset = Test.objects.all()
    serializer_class = TestSerializer

Ce ModelViewSet est livré avec des implémentations par défaut pour .list(), .retrieve(), .create(), .update() et .destroy(). Quels sont ceux que vous pouvez remplacer (personnaliser) selon vos besoins

Renvoi de JSON personnalisé depuis .retrieve() et/ou .list() dans ModelViewSet

Par exemple. pour remplacer .retrieve() pour retourner la vue personnalisée lors de la récupération d'un seul objet. Nous pouvons jeter un oeil à la implémentation par défaut qui ressemble à ceci :

def retrieve(self, request, *args, **kwargs):
    instance = self.get_object()
    serializer = self.get_serializer(instance)
    return Response(serializer.data)

Ainsi, à titre d'exemple pour retourner un JSON personnalisé:

class TestViewSet(viewsets.ModelViewSet):
    queryset = Test.objects.all()
    serializer_class = TestSerializer

    def retrieve(self, request, *args, **kwargs):
        return Response({'something': 'my custom JSON'})

    def list(self, request, *args, **kwargs):
        return Response({'something': 'my custom JSON'})
55
bakkal

Il existe 2 façons de personnaliser la réponse dans Vues basées sur les classes avec ModelViewSet

Solution 1: personnalisé dans views.py

class StoryViewSet(viewsets.ModelViewSet):
    permission_classes = (permissions.AllowAny,)
    queryset = Story.objects.all()
    serializer_class = StorySerializer

    def retrieve(self, request, *args, **kwargs):
        # ret = super(StoryViewSet, self).retrieve(request)
        return Response({'key': 'single value'})

    def list(self, request, *args, **kwargs):
        # ret = super(StoryViewSet, self).list(request)
        return Response({'key': 'list value'})

Solution 2: personnalisé dans serializers.py (je recommande cette solution)

class StorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Story
        fields = "__all__"

    def to_representation(self, instance):
        ret = super(StorySerializer, self).to_representation(instance)
        # check the request is list view or detail view
        is_list_view = isinstance(self.instance, list)
        extra_ret = {'key': 'list value'} if is_list_view else {'key': 'single value'}
        ret.update(extra_ret)
        return ret
0
HoangYell