I’ve been trying unsuccesfully to make a POST request to my API end point, and I always get an error. My setup is a django server with a rest API, and I’m trying to add a reservation to the Booking Model, using fetch.
This is the code inside my "onSubmit" js function (when the submit button is clicked):
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));
models.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')
forms.py
class BookingForm(ModelForm):
class Meta:
model = Booking
fields = ['date', 'hour', 'client']
views.py (of the api endpoint /api/booking/
class BookingView(generics.ListCreateAPIView):
queryset = Booking.objects.all()
serializer_class = BookingSerializer
So this is the error I get in the Chrome JS console:
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
Any idea what is the problem?
2
Answers
Your content type for the body is JSON but you are trying to send FormData. Convert the FormData to JSON first before putting it in the request body.
csrf
is not required in REST APIs services. Thus, you do not need to set any headers in your request. Although, you have an authentication system in place and your view just does not know how to handle it:Aside from that it is always good practice to use the latest features such as
arrow functions
andasync/await
, introduced with ES6. That being said, your template should be similar to this: