Django rest framework response : "The submitted data was not a file. Check the encoding type on the form."
I'm currently testing uploading multiple files(4 images) at once using Postman. Here is how's its configured on Postman.
The key is file_list and the values are the 4 image files I've uploaded to postman. I've configured My Django rest framework view like the following :
class PostImageValidate(APIView):
permission_classes = (IsAuthenticated, IsNotSuspended)
def put(self, request):
request_data = request.data.dict()
serializer = TempImageSerializer(data=request_data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
file_list = data.get("file_list")
uploaded_files = data.pop(file_list)
results = []
for file in uploaded_files:
results.append({"filename": file.name, "size": file.size, "status": "Processed})
return Response({"message": "Images processed successfully", "results": results, "number of items": len(results)}, status=status.HTTP_201_CREATED)
class TempImageSerializer(serializers.Serializer):
file_list = serializers.ListField(child=serializers.FileField(max_length=150, allow_empty_file=False), allow_empty=False)
However, I get the following response after a span of 5-6 seconds of making a request.
{
"file_list": {
"0": [
"The submitted data was not a file. Check the encoding type on the form."
],
"1": [
"The submitted data was not a file. Check the encoding type on the form."
],
}
}
# The key "0" ,"1" extends up to 460 with the same statement above.
I haven't been able to solve the above. My objective is to make sure it returns the Response as expected. Only then I intend to move onto my end of processing those files, the code for which hasn't been inserted.
I made minimal working code for test it and it seems problem makes .dict() in
request_data = request.data.dict()
It creates dictionary with single file (even if there are more files) - like this
{'file_list': <InMemoryUploadedFile: lenna.png (image/png)>}
but code needs list (even if there is only one file) - like this
{'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}
(so later it treats this single file as list of objects and it creates so many wrong items in response)
Code works correctly if I skip .dict()
request_data = request.data
# <QueryDict: {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>
or I use standard dict(...) if you really need standard dict instead of QueryDict
request_data = dict(request.data)
# {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>
Works also with requests.FILES
request_data = {"file_list": request.FILES.getlist("file_list")}
Other problem is in lines
file_list = data.get("file_list")
uploaded_files = data.pop(file_list)
It has to be string "file_list" instead of variable file_list
# no need to use `data.get()`
uploaded_files = data.pop("file_list")
Full class used for tests
class PostImageValidate(APIView):
# permission_classes = (IsAuthenticated, IsNotSuspended)
def put(self, request):
print("\n=== put ===\n")
print("=== request.data ===")
print(request.data)
print("=== request.data.dict() ===")
print(request.data.dict())
print("=== request.data.lists() ===")
print(request.data.lists())
print(list(request.data.lists()))
print("=== dict(request.data) ===")
print(dict(request.data))
print('=== request.FILES.getlist("file_list") ===')
print(request.FILES.getlist("file_list"))
# request_data = request.data.dict() # WRONG
# request_data = dict(request.data)
request_data = request.data
# request_data = {"file_list": request.FILES.getlist("file_list")}
print("=== request_data ===")
print(request_data)
serializer = TempImageSerializer(data=request_data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
# uploaded_files = data.pop("file_list")
uploaded_files = data.get("file_list")
print("=== uploaded_files ===")
print(uploaded_files)
results = []
for file in uploaded_files:
results.append(
{"filename": file.name, "size": file.size, "status": "Processed"}
)
output = {
"message": "Images processed successfully",
"results": results,
"number of items": len(results),
}
return Response(output, status=status.HTTP_201_CREATED)
I tested it with curl in console (on Linux Mint)
curl -X PUT \
-F "file_list=@lenna.jpg" \
-F "file_list=@lenna.png" \
-F "other=Hello World!" \
http://127.0.0.1:8000/api/upload/