Search code examples
djangodjango-models

Django: ClearableFileInput does not support uploading multiple files -- error?


I am trying to add an option to add multiple files at once in a form, and I found the solution with using ClearableFileInput:

class Image(models.Model):
    id = models.AutoField(primary_key=True)
    post = models.ForeignKey(BlogEntry, on_delete=models.CASCADE)
    photo = models.ImageField(null=True, blank=True, upload_to='media/')
    photo_objects = models.Manager()


class ImageForm(forms.ModelForm):
    class Meta:
        model = Image
        fields = ['photo', ]
        widgets = {

            'photo': forms.ClearableFileInput(attrs={'multiple': True})

        }

However, when I tried to run it using runserver, it gave me an error. Can somebody help me with fixing it? Is there another straightforward option to add multiple files?

I tried to search difference solutions on the internet but some of them did not work while others looked too complicated for my current level. I also see this option to upload multiple files in the official documentation (https://docs.djangoproject.com/en/dev/topics/http/file-uploads/) but I wonder if there is a simpler version in which I would not need to create MultipleFileInput and MultipleFileField by myself. Is there something in Django to enable multiple file upload?


Solution

  • I once experienced the same issue, came across many articles and answers on the net but all were suggesting to use
    forms.ClearableFileInput(attrs={'multiple': True}) .
    The only option that worked was the one provided in the official documentation (which you are finding hard to implement). For your case, your code in the file forms.py (the one which contains class ImageForm) will have to include this -

    class MultipleFileInput(forms.ClearableFileInput):
        allow_multiple_selected = True
    
    class MultipleFileField(forms.FileField):
        def __init__(self, *args, **kwargs):
            kwargs.setdefault("widget", MultipleFileInput())
            super().__init__(*args, **kwargs)
    
        def clean(self, data, initial=None):
            single_file_clean = super().clean
            if isinstance(data, (list, tuple)):
                result = [single_file_clean(d, initial) for d in data]
            else:
                result = single_file_clean(data, initial)
            return result
    
    class ImageForm(forms.ModelForm):
        photo = MultipleFileField(label='Select files', required=False)
    
        class Meta:
            model = Image
            fields = ['photo', ]
    

    Remember that you'll have to update your function accepting the request/files in the views.py accordingly. For example -

    def function(request):
        if request.method == 'POST' :
            uploaded_images = request.FILES.getlist('photo')
            for image in uploaded_images:
                #your task here (What you want to do with the image)
    

    Let me know if this works!