Как вернуть пользовательский JSON в Django REST Framework

Я пытаюсь вернуть пользовательский json с помощью get_queryset но всегда получаю 404 error в ответ.

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')

Если я удалю все, начиная с def я получу правильный ответ со стандартными json-данными. Что я делаю неправильно?

Ответ 1

Если вам не нужен ModelViewSet и вы хотите использовать собственный JSON для запроса GET

Вы также можете использовать APIView, который не требует модели

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

а также

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

С ModelViewSet

Вы поместили пользовательский JSON в get_queryset, что неправильно. Если вы хотите использовать ModelViewSet, этого должно быть достаточно:

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

Этот ModelViewSet поставляется с реализациями по умолчанию для .list(), .retrieve(), .create(), .update() и .destroy(). Которые доступны для вас, чтобы переопределить (настроить) по мере необходимости

Возврат пользовательского JSON из .retrieve() и/или .list() в ModelViewSet

Например, переопределить .retrieve() чтобы вернуть пользовательский вид при извлечении одного объекта. Мы можем взглянуть на реализацию по умолчанию, которая выглядит так:

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

Итак, в качестве примера, чтобы вернуть пользовательский JSON:

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'})

Ответ 2

Есть 2 способа настроить ответ в представлениях на основе классов с ModelViewSet

Решение 1: обычай в 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'})

Решение 2: пользовательский в serializers.py (я рекомендую это решение)

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