I know this question has been a dozen times, but I just can’t seem to get any of the answers to work.
I have an app with a React frontend and Django Rest backend, and I’m trying to send an array of objects in a request. I’ve gotten this to work in Postman in both the raw JSON input as well as the FormData there:
So I know that my backend should be able to handle it fine, but no matter what I try in my React code I get the same 400 error. Here is my (slightly trimmed) function from my front end:
const formData = new FormData();
if(data.photo.length >= 1) {
formData.append('photo', data.photo[0]);
}
formData.append('recipe_name', data.recipe_name);
formData.append('ingredients', JSON.stringify(data.ingredients));
// data.ingredients.forEach(element => {
// console.log(JSON.stringify(element))
// formData.append('ingredients[]', JSON.stringify(element))
// });
// for(let i=0; i < data.ingredients.length; i++) {
// console.log(data.ingredients[i])
// formData.append('ingredients[]', JSON.stringify(data.ingredients[i]))
// }
console.log(formData)
const config = {
headers: {
'content-type': 'multipart/form-data',
'Authorization': localStorage.getItem('access_token') ?
'Bearer ' + localStorage.getItem('access_token') :
null,
},
};
axiosInstance.post('/recipes/', formData, config).then((response) => {
console.log(response.data);
navigate('/recipe/' + response.data.id);
});
I left some commented out code of different things I’ve tried, but to summarize, I’ve tried:
formData.append('ingredients', data.ingredients);
formData.append('ingredients', JSON.stringify(data.ingredients));
formData.append('ingredients[]', JSON.stringify(data.ingredients));
data.ingredients.forEach(element => {
formData.append('ingredients[]', JSON.stringify(element))
});
data.ingredients.forEach(element => {
formData.append('ingredients', JSON.stringify(element))
});
data.ingredients.forEach(element => {
formData.append('ingredients', element)
});
data.ingredients.forEach(element => {
formData.append('ingredients[]', element)
});
I’ve even tried doing a traditional for-loop with the same permutations, but to no success.
I’ve also tried looking into the data itself that I’m sending from the front end, but as far as I can tell there’s nothing wrong with it either. Here is the raw data coming from my form component:
and the individual elements (printed out in the forEach loop):
and those same elements passed through JSON.stringify()
I’m really at a loss on what else to try, it feels like I’ve basically tried everything, and all of the answers for this same question I’ve found on previous threads all suggests what I’ve tried. Any help would be greatly appreciated!
2
Answers
I think you have to add it as a json file blob:
When you send data in a POST (or any other method) request, the data is in the body of the request. You can send data with any content-type, but typically you will use either
application/x-www-form-urlencoded
,multipart/form-data
or any other text format (the first are also text formats…) likeapplication/json
,text/xml
etc.If you use
application/x-www-form-urlencoded
all entries are key/value pairs. JSON can be send as a string as one of the values. If you usemultipart/form-data
all entries are also key/value pairs, but you have more options like sending files, and a file can have a name and a content-type. So, either you send JSON as a string in a key/value pair or as a file (just like Cassiano Franco write in his answer). The FormData object can be used for preparingmultipart/form-data
content. So, by using the FormData object, JSON is either as string to a key/value pair or as a file.The last option is to send everything as text, like
application/json
. So, the content-type of the request isapplication/json
and the body of the request is as string created based on something likeJSON.stringify(jsonObject)
.Receiving a POST request on the server side with any of the above mentioned content-types will look different. So, depending on the content-type you need to handle data and files in different ways.
This is just the long argument for me to give Cassiano Franco a vote.