Amandeep Dhiman
Amandeep Dhiman

Reputation: 624

upload multiple files in django

I am new to django, I am trying to upload more than one file from the browser and store them somewhere in computer storage but I am not storing them successfully with this code please help me out to find my mistake or improvements that I can do. Thanks in advance to help.

views.py

    from django.shortcuts import render
    from django.http import HttpResponse
    # Create your views here.

    def Form(request):
        return render(request, "index/form.html", {})

    def Upload(request):
        for count, x in enumerate(request.FILES.getlist("files")):
            def process(f):
                with open('/Users/benq/djangogirls/upload/media/file_' + str(count), 'wb+') as destination:
                    for chunk in f.chunks():
                        destination.write(chunk) 
            process(x)
        return HttpResponse("File(s) uploaded!")

app/urls.py

from django.conf.urls import url
from index import views

urlpatterns = [
    url(r'^form/$', views.Form),
    url(r'^upload/$', views.Upload)
]

form.html

<form method="post" action="../upload/" entype="multipart/form-data"> {% csrf_token %}
<input type="file" name="files" multiple />
<input type="submit" value="Upload" />

Upvotes: 12

Views: 57288

Answers (5)

katomaso
katomaso

Reputation: 423

As @dnet pointed out. The mistake is in your HTML in the form tag. If you don't specify enctype manually, the files will never get sent out (tested even with latest browser and django 4.2). Unfortunately for you, you didn't close the <form> and you have a spelling mistake in enCtype.

<form method="POST" enctype="multipart/form-data">{% csrf_token %}
    <input type="file" name="posts" multiple>
    <button type="submit">Import</button>
</form>
# in your views.py
def upload_file(request):
   for file in request.FILES.getlist('posts'):
       process(file)  # file is an instance of django.core.files.File
   return redirect('app:wherever')

Upvotes: 0

PrynsTag
PrynsTag

Reputation: 311

Just an update from Django 3.2 and above. According to docs you have to:

If you want to upload multiple files using one form field, set the multiple HTML attribute of field’s widget:

from django import forms

class FileFieldForm(forms.Form):
    file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

Then override the post method of your FormView subclass to handle multiple file uploads:

from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldView(FormView):
    form_class = FileFieldForm
    template_name = 'upload.html'  # Replace with your template.
    success_url = '...'  # Replace with your URL or reverse().

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('file_field')
        if form.is_valid():
            for f in files:
                ...  # Do something with each file.
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

Upvotes: 3

AKASH GUDADHE
AKASH GUDADHE

Reputation: 367

Answer from official django documentation

 file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

https://docs.djangoproject.com/en/3.0/topics/http/file-uploads/#uploading-multiple-files

Upvotes: 8

Tyler Alev
Tyler Alev

Reputation: 21

I was able to solve the multi uploads portion in the create view here: Django Class based UpdateView with Form for Multiple Uploaded Files , however, now the update get function is what I am currently stuck on.

Upvotes: 0

Dimitris Kougioumtzis
Dimitris Kougioumtzis

Reputation: 2439

my model to save Document

class Document(models.Model):
  file = models.FileField('Document', upload_to='mydocs/')

  @property
  def filename(self):
     name = self.file.name.split("/")[1].replace('_',' ').replace('-',' ')
     return name
  def get_absolute_url(self):
     return reverse('myapp:document-detail', kwargs={'pk': self.pk})

you can try a django create view in my code i use this DocumentCreateView

class DocumentCreate(CreateView):
   model = Document
   fields = ['file']

   def form_valid(self, form):
     obj = form.save(commit=False)
     if self.request.FILES:
        for f in self.request.FILES.getlist('file'):
            obj = self.model.objects.create(file=f)

   return super(DocumentCreate, self).form_valid(form)

my form html file

<script>
  $(document).ready(function(){
    $('#id_file').attr("multiple","true");

  })
 </script>
<form method="post" enctype="multipart/form-data" action="">{% csrf_token %}
 {{ form.file }}
 <input type="submit" value="upload" />

</form>

Upvotes: 20

Related Questions