如何使用 JS fetch 成功向 Django REST API 发出 POST 请求

问题描述 投票:0回答:2

我一直尝试向 API 端点发出 POST 请求,但没有成功,并且总是收到错误。我的设置是一个带有 REST API 的 Django 服务器,我正在尝试使用 fetch 将预订添加到预订模型中。

这是我的“onSubmit”js 函数中的代码(当单击提交按钮时):

                csrf = document.getElementsByName("csrfmiddlewaretoken")[0].value;
                const formdata = new FormData(form);
                fetch('/api/booking/', {
                    method: 'POST',
                    headers: {
                        "X-CSRF-Token":csrf,
                        "Content-Type": "application/json"
                    },
                    credentials: "same-origin",
                    body: formdata
                })
                .then(res => res.json())
                .then(data => console.log(data));

模型.py

class Booking(models.Model):
    client = models.ForeignKey(User,  on_delete=models.CASCADE, null=True)
    date = models.DateField(null=True)
    hour = models.SmallIntegerField(
        null=False,
        default=12,
        validators=[ #from 8am to 10pm
            MaxValueValidator(22),
            MinValueValidator(8)
        ],
    )
    
    class Meta:
        unique_together = ('date', 'hour')

表格.py

class BookingForm(ModelForm):
    class Meta:
        model = Booking
        fields = ['date', 'hour', 'client']

views.py(api 端点 /api/booking/

class BookingView(generics.ListCreateAPIView):
    queryset = Booking.objects.all()
    serializer_class = BookingSerializer

这就是我在 Chrome JS 控制台中收到的错误:

book:159     POST http://127.0.0.1:8000/api/booking/ 400 (Bad Request)
onSubmit @ book:159
book:169 {detail: 'JSON parse error - Expecting value: line 1 column 1 (char 0)'}detail: "JSON parse error - Expecting value: line 1 column 1 (char 0)"[[Prototype]]: Object

知道问题出在哪里吗?

javascript django post fetch-api
2个回答
0
投票

您的正文内容类型是 JSON,但您正在尝试发送 FormData。先将 FormData 转换为 JSON,然后再将其放入请求正文中。

var object = {};
formdata.forEach(function(value,key){
object[key] = value});

fetch('/api/booking/', {
   method: 'POST',
   headers: {
      "X-CSRF-Token":csrf,
      "Content-Type": "application/json"
       },
   credentials: "same-origin",
   body: JSON.stringify(object)
   })

0
投票
REST API 服务中不需要

csrf
。因此,您不需要在请求中设置任何标头。虽然,您有一个身份验证系统,但您的视图只是不知道如何处理它:

class BookingListCreateAPIView(ListCreateAPIView):
    queryset = Booking.objects.all()
    serializer_class = BookingSerializer
    authentication_classes = [BasicAuthentication]

除此之外,使用 ES6 引入的最新功能(例如

arrow functions
async/await
)始终是一个好的做法。话虽如此,您的模板应该与此类似:

<body>
    <form>
        {{form}}
        <input type="button" value="Submit" onclick="sendForm()">
    </form>

    <script>
        const sendForm = async (event) => {
            const url = 'http://localhost:8000/api/bookings/';

            const formElement = document.querySelector("form");
            const formData = new FormData(formElement);
            
            const res = await fetch(url, { 
                method: "POST", 
                body: formData 
            });

            if (res.status === 201) {
                console.log('Booking successfully created!');
            }
        }
    </script>
</body>
© www.soinside.com 2019 - 2024. All rights reserved.