Could you please help me solve this issue. I spent around 6 hours on this. I want to upload image from react to django admin, but when I insert article and submit, I am getting this error: "The submitted data was not a file. Check the encoding type on the form". Pretty simple question but can't seem to find it anywhere online. I tried everything and watched lots of videos on youtube but could not solve it. Please help me
here is my view
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all().order_by("price")
serializer_class = ArticleSerializer
def post(self, request, *args, **kwargs):
image = request.data['image']
tour_title = request.data['tour_title']
Article.object.create(tour_title=tour_title, image=image)
return HttpResponse({'message': 'Image added'}, status=200)
def create(self, request, *args, **kwargs):
data = request.data
token = request.headers.get('Authorization').split(" ")[1]
user = Token.objects.get(key=token).user
if not user.status == 2:
return Response({"error": "user must be activated"})
data["author"] = user
serializer = ArticleSerializer(data=data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response({"payload": serializer.data})
# print(request.headers.get('Authorization'), "request.user")
# return Response({"success": True})
@action(detail=False)
def get_articles_by_user(self, request, *args, **kwargs):
token = request.headers.get('Authorization').split(" ")[1]
user = Token.objects.get(key=token).user
articles = self.get_queryset().filter(author=user)
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
here is my serializer
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = [
"id",
"tour_title",
"image",
"country",
"price",
"duration",
"description",
"author",
]
here is my model
def upload_path(instance, filename):
return '/'.join(['images', str(instance.tour_title), filename])
class Article(models.Model):
tour_title = models.CharField(max_length=100)
image = models.ImageField(blank=True, null=True, upload_to=upload_path)
country = models.CharField(max_length=100)
price = models.DecimalField(max_digits=20, decimal_places=2)
duration = models.CharField(max_length=100)
description = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL, default=None, on_delete=models.CASCADE)
def __str__(self):
return self.tour_title
and this is my form in react
import React, { useState, useEffect } from "react";
import APIService from "./ApiService";
import { useCookies } from "react-cookie";
export default function Form(props) {
const [tour_title, setTour_title] = useState("");
const [image, setImage] = useState("");
const [country, setCountry] = useState("");
const [price, setPrice] = useState("");
const [duration, setDuration] = useState("");
const [description, setDescription] = useState("");
const [token, setToken] = useCookies(["mytoken"]);
useEffect(() => {
setTour_title(props.article.tour_title);
setImage(props.article.image);
setCountry(props.article.country);
setPrice(props.article.price);
setDuration(props.article.duration);
setDescription(props.article.description);
}, [props.article]);
const updateArticle = () => {
APIService.UpdateArticle(
props.article.id,
{ tour_title, image, country, price, duration, description },
token["mytoken"]
).then((resp) => props.updatedInformation(resp));
};
const insertArticle = () => {
APIService.InsertArticle({
tour_title,
image,
country,
price,
duration,
description,
}, token["mytoken"]).then((resp) => props.insertedInformation(resp));
};
return (
<div>
{props.article ? (
<div className="mb-3">
<label htmlFor="tour_title" className="form-label">
Tour title
</label>
<input
type="text"
className="form-control"
id="tour_title"
placeholder="Please enter the tour title"
// value={tour_title || ""}
onChange={(e) => setTour_title(e.target.value)}
/>
<label htmlFor="image" className="form-label">
Tour image
</label>
<input
type="file"
className="form-control"
name="image"
id="image"
accept="image/*"
file={image}
onChange={(e) => setImage(e.target.files[0])}
/> <br/>
<img src={image} width="100px"/>
<br/>
<label htmlFor="country" className="form-label">
Country
</label>
<input
// required={true}
type="text"
className="form-control"
id="country"
// value={country}
onChange={(e) => setCountry(e.target.value)}
/>
<label htmlFor="price" className="form-label">
Price
</label>
<input
type="number"
className="form-control"
id="price"
// value={price}
onChange={(e) => setPrice(e.target.value)}
/>
<label htmlFor="duration" className="form-label">
Duration
</label>
<input
type="text"
className="form-control"
id="duration"
// value={duration}
onChange={(e) => setDuration(e.target.value)}
/>
<label htmlFor="description" className="form-label">
Description
</label>
<textarea
className="form-control"
id="description"
rows="5"
// value={description}
onChange={(e) => setDescription(e.target.value)}
></textarea>
<br />
{props.article.id ? (
<button onClick={updateArticle} className="btn btn-success">
Update article
</button>
) : (
<button
onClick={insertArticle}
className="btn btn-success"
disabled={!tour_title || !country || !price || !duration || !description}
>
Insert article
</button>
)}
</div>
) : null}
</div>
);
}
my API in separate file
static InsertArticle(body, token) {
return fetch('http://127.0.0.1:8000/api/articles/', {
method:'POST',
headers: {
'Content-Type':'application/json',
'Authorization':`Token ${token}`
},
body:JSON.stringify(body)
}).then(resp => resp.json())
.then((data) => {
if (!data.payload && data.error) {
alert(data.error);
throw "Error";
} else {
return data.payload;
}
})
.catch(err => {
console.log(err)
});
}
Please help me with this problem