i am trying to save an object with an image using django restframework but when i use the FormParser and MultiPartParser classes the request.data object get seemingly encoded msgs and when i try to decode using utf-8 it outputs an error saying this data is not utf-8
i want to have access to the request.data data and be able to save the image for future requests
here is my view function:
@parser_classes([FormParser, MultiPartParser])
@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def products(request):
if request.method == 'POST':
print(request.data)
serializer = ProductSerializer(data=request.data)
serializer.initial_data['user'] = request.user.pk
serializer.initial_data['price'] = float(
request.data['price'])
serializer.initial_data['quantity'] = int(
request.data['quantity'])
if serializer.is_valid():
serializer.save()
return Response({'message': "product added"}, status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
my front end code:
export const addProduct = async (product) => {
const fd = new FormData();
fd.append("name", product.name);
fd.append("price", product.price);
fd.append("quantity", product.quantity);
fd.append("image_url", product.image_url);
console.log(product.image_url) //this prints a file object
const response = await fetch(`${URL}/products`, {
method: "POST",
headers: {
"Content-Type": `multipart/form-data; boundary=${fd._boundary}`,
},
body: fd,
})
return response
}
CodePudding user response:
The image data is not being encoded as UTF-8 (Maybe! and if so), you can use the FileField or ImageField field in your serializer, along with the FormParser and MultiPartParser classes!
[UPDATED] Your view should be:
@parser_classes([FormParser, MultiPartParser])
@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def products(request):
if request.method == 'POST':
serializer = ProductSerializer(data=request.data)
serializer.initial_data['user'] = request.user.pk
if 'price' in request.data:
serializer.initial_data['price'] = float(request.data['price'])
else:
return Response({'error': 'price not found in request data'}, status=status.HTTP_400_BAD_REQUEST)
if 'quantity' in request.data:
serializer.initial_data['quantity'] = int(request.data['quantity'])
else:
return Response({'error': 'quantity not found in request data'}, status=status.HTTP_400_BAD_REQUEST)
if serializer.is_valid():
serializer.save()
return Response({'message': "product added"}, status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
And the serializer:
class ProductSerializer(serializers.ModelSerializer):
image_url = serializers.ImageField()
class Meta:
model = Product
fields = ['name', 'price', 'quantity', 'image_url', 'user']
CodePudding user response:
so when i removed my headers it worked fine, so apparently if you choose to use multipart/form-data, the boundary must not appear in the file data that the server eventually receives.
The problem with multipart/form-data is that the boundary separator must not be present in the file data (see RFC 2388; section 5.2 also includes a rather lame excuse for not having a proper aggregate MIME type that avoids this problem).
so i fixed it by removing the boundary in the front end which makes my frontend code look something like this
const fd = new FormData();
fd.append("name", product.name);
fd.append("price", product.price);
fd.append("quantity", product.quantity);
fd.append("image_url", product.image_url);
console.log(product.image_url) // this print a File object
const response = await fetch(`${URL}/products`, {
method: "POST",
headers: {
Authorization: `token ${localStorage.getItem("auth")}`
},
body: fd,
})