Ajax-вызов к DRF API "Вы не можете получить доступ к телу после чтения из потока данных запроса" - PullRequest
1 голос
/ 30 сентября 2019

Привет! Я пытаюсь использовать Ajax для отправки запроса POST (включая данные json) на мой API Django Rest Framework после того, как пользователь нажмет кнопку save в форме. Я пытался с почтальоном, и он работал, но когда я позвонил с AJAX, он поднял RawPostDataException Ошибка

Мой API в views.py:

class FilterView(APIView):
    authentication_classes = [SessionAuthentication, JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        login_user = request.user
        paginator = ListPagination()
        queryset = Filter.objects.filter(user=login_user).all().order_by('-pk')
        context = paginator.paginate_queryset(queryset, request)
        serializer = FilterSerializer(context, many=True)

        return paginator.get_paginated_response(serializer.data)

    def post(self, request):
        login_user = request.user
        received_json_data=json.loads(request.body)
        valid_ser = FilterSerializer(data=received_json_data)
        if valid_ser.is_valid():
            post_data = received_json_data["data"]
            filter = Filter.objects.create(data=post_data, user=login_user)
            filter.save()

            return JsonResponse({'code':'200','data': filter.id}, status=200)
        else:
            return JsonResponse({'code':'400','errors':valid_ser.errors}, status=400)

Мой сериализатор:

class FilterSerializer(serializers.ModelSerializer):
    user = serializers.IntegerField(required=False, source="user.id")

    def validate_data(self, data):
        if type(data) is not dict:
            raise serializers.ValidationError("invalid JSON object")

    class Meta:
        model = Filter
        fields = ('__all__')
        extra_kwargs = {'data': {'required': True}}

И мой ajax-запрос в html:

$('#save').click( function(event) {
                event.preventDefault();
                var type = $('#type').val();
                var price_min = $('#price_min').val();
                var price_max = $('#price_max').val();
                var size_min = $('#size_min').val();
                var size_max = $('#size_max').val();
                var city = $('#city').val();
                var district = $('#district').val();
                var ward = $('#ward').val();
                var street = $('#street').val();
                var frontend_min = $('#front_end_min').val();
                var frontend_max = $('#front_end_max').val();
                var road = $('#road').val();
                var floor = $('#floor').val();
                var bedroom = $('#bedroom').val();
                var living_room = $('#living_room').val();
                var toilet = $('#toilet').val();
                var direction = $('#direction').val();
                var balcony = $('#balcony').val();
                var filter_data = {
                    'type': type,
                    'price_min': price_min,
                    'price_max': price_max,
                    'size_min': size_min,
                    'size_max': size_max,
                    'city': city,
                    'district': district,
                    'ward': ward,
                    'street': street,
                    'frontend_min': frontend_min,
                    'frontend_max': frontend_max,
                    'road': road,
                    'floor': floor,
                    'bedroom': bedroom,
                    'living_room': living_room,
                    'toilet': toilet,
                    'direction': direction,
                    'balcony': balcony,
                }
                // console.log(filter_data);
                $.ajax({
                    type: "POST",
                    url: "/api/filters/",
                    beforeSend: function (xhr) {    
                        xhr.setRequestHeader('X-CSRFToken', '{{csrf_token}}');
                    },
                    data: JSON.stringify({"data": filter_data}),
                    success: function (data) {
                        if (data.code == 200) {
                            alert("added filter");
                        }
                    }
                });
                return false;
            });

Когда я звоню с использованием Ajax, на моем сервере django возвращается следующая ошибка:

raise RawPostDataException("You cannot access body after reading from request's data stream")
web_1       | django.http.request.RawPostDataException: You cannot access body after reading from request's data stream

Я пыталсяи он работал на моем POSTMAN, я не знаю, почему он не работает на вызове ajax

Я прочитал об этой ошибке и у меня есть много предложений, используя request.data вместо request.body, но когда я использовалон, по моему мнению, при вызове Ajax возвращает:

TypeError: объект JSON должен быть str, bytes или bytearray, а не 'QueryDict'

и на POSTMANвернуть ошибку:

"detail": "Неподдерживаемый тип носителя \" text / plain \ "в запросе."

Я немного застрял на том, как сделатьэта работа как для POSTMAN, так и для вызова Ajax, любая помощь будет хороша

1 Ответ

0 голосов
/ 30 сентября 2019

Я исправил это, изменив request.body на request.data, а также изменил свой код ajax

receive_json_data = request.data

и код ajax:

$.ajax({
        type: "POST",
        url: "/api/filters/",
        beforeSend: function (xhr) {    
        xhr.setRequestHeader('X-CSRFToken', '{{csrf_token}}');
         },
        contentType: "application/json",
        dataType: 'json',
        data: JSON.stringify({"data": filter_data}),
        success: function (data) {
        if (data.code == 200) {
             alert("added filter");
            }
         }
      });
...