HanXu
HanXu

Reputation: 5597

Django rest framework uploading multiple files

I am using django-rest-framework.

Is there a way to handle multiple file uploading? It seems that even the client is sending multiple files (thourgh a web browser), the MultiPartParser will only select the first file.

Upvotes: 8

Views: 7989

Answers (3)

simon
simon

Reputation: 16330

I realize this is an old question, but I just spent some time banging my head against this. The issue is that Django's MultiPartParser, which DRF uses, returns files as a MultiValueDict. When DRF then then adds the files back to the data that is passed to the serializer, it does so using .update() on the data (which is an OrderedDict) in request.Request._load_data_and_files(). The result is that if multiple files are uploaded with the same key, only the last one survives [1] and makes it as far as the serializer.

Django's documentation recommends over-riding the .post() method in the FormView if using a form [2]. An alternative is to subclass the parser, and call dict() on the files MultiValueDict before returning it, so that lists are returned instead of being reduced to their last value. I'm using the second option, as I'm subclassing the parser already anyway.

[1] https://docs.djangoproject.com/en/dev/_modules/django/utils/datastructures/

[2] https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#uploading-multiple-files

Upvotes: 4

chubao
chubao

Reputation: 6011

You may access the file list through request.FILES.getlist('<your_payload_files_key>').

I got the answer from this SO answer.

Upvotes: 3

Vasili Korol
Vasili Korol

Reputation: 81

If you intend to validate multiple uploaded files, then you will have to write your own serializer for that. There is a serializers.ListField for validating lists of objects. I haven't tried this, but I believe you could implement a simple serializer like this:

class FileListSerializer ( serializers.Serializer ) :

    files = serializers.ListField(
                child=serializers.FileField( max_length=100000,
                                             allow_empty_file=False,
                                             use_url=False )
            )

Then probably you could validate the files by calling the serializer from the view:

files = list( request.FILES.values() )
files_serializer = FileListSerializer( data={"files": files} )
if not file_serializer.is_valid() :
    # handle error
    ...

Upvotes: 2

Related Questions