Django multifile upload doesn't send files to directory

1k Views Asked by At

I'd like to implement a multifile upload feature into a site. There is already an upload feature on the site, but for single files. I'm following loosely the Simple Is Better Than Complex: Django Multiple Files Upload Using Ajax.

My code:

views->mulit_upload.py

class BasicUploadView(View):
    def get(self, request):
        files_list = Multi_File.objects.all()

        #files_list = ['testing_123']

        print ("files_list: {0}".format(files_list))
        return render(self.request, 'myproject/multi_upload.html', {'filesList': files_list})

    def post(self, request):
        form = FileForm(self.request.POST, self.request.FILES)
        if form.is_valid():
            multiFile = form.save()
            data = {'is_valid': True, 'name': multiFile.file.name, 'url': multiFile.file.url}
        else:
            data = {'is_valid': False}
        return JsonResponse(data)

models.py

class Multi_File(models.Model):
    title = models.CharField(max_length=255, blank=True)
    file = models.FileField(upload_to='files/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

forms.py

class FileForm(forms.ModelForm):
    class Meta:
        model = Multi_File
        fields = ('file', )

multi_upload.html

{% load static %}

{% block javascript %}
  <script src="{% static 'myproject/js/jQuery-File-Upload-9.14.1/js/vendor/jquery.ui.widget.js' %}"></script>
  <script src="{% static 'myproject/js/jQuery-File-Upload-9.14.1/js/jquery.iframe-transport.js' %}"></script>
  <script src="{% static 'myproject/js/jQuery-File-Upload-9.14.1/js/jquery.fileupload.js' %}"></script>

  <script src="{% static 'myproject/upload-files.js' %}"></script>
{% endblock %}

{# 1. BUTTON TO TRIGGER THE ACTION #}
<div class="col-md-4">
<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  <input type="file" name="myfile" multiple>
  <button type="submit">Upload<span class="glyphicon glyphicon-cloud-upload"></span> </button>
</form>
</div>

{# 2. FILE INPUT TO BE USED BY THE PLUG-IN #}
<input id="fileupload" type="file" name="myfile" multiple
       style="display: none;"
       data-url="{% url 'myproject:multi_import' %}"
       data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>

{# 3. TABLE TO DISPLAY THE UPLOADED PHOTOS #}
<table id="gallery" class="table table-bordered">
  <thead>
    <tr>
      <th>Uploaded Files:</th>
    </tr>
  </thead>
  <tbody>
    {% for aFile in filesList %}
      <tr>
        <td><a href="{{ aFile.file.url }}">{{ aFile.file.name }}</a></td>
      </tr>
    {% endfor %}
  </tbody>
</table>

upload_files.js

$(function () {
  /* 1. OPEN THE FILE EXPLORER WINDOW */
  $(".js-upload-files").click(function () {
    $("#fileupload").click();
  });

  /* 2. INITIALIZE THE FILE UPLOAD COMPONENT */
  $("#fileupload").fileupload({
    dataType: 'json',
    done: function (e, data) {  /* 3. PROCESS THE RESPONSE FROM THE SERVER */
      if (data.result.is_valid) {
        $("#gallery tbody").prepend(
          "<tr><td><a href='" + data.result.url + "'>" + data.result.name + "</a></td></tr>"
        )
      }
    }
  });

});

Problems so far: 1. Upload doesn't work when clicking on the button. The box appears, I can select numerous files and "upload" to the page i.e. it says 2 files selected. But then clicking "Upload" gives the error:

{"is_valid": false}

This comes from the view (mulit_uploade.py) but I'm a bit confused why

  1. I'd like to use the base.html that was also used for the single upload feature. So when I add {% extends "myproject/base.html" %} to the multi_upload.html, a new problem appears that doesn't appear when I just use the single upload feature:

    Reverse for 'myproject_about' not found. 'myproject_about' is not a valid view function or pattern name:

    Learn more »

    NoReverseMatch at /myproject/import/

    Reverse for 'myproject_about' not found. 'myproject_about' is not a valid view function or pattern name

1

There are 1 best solutions below

2
On

To start off you will need a formset(https://docs.djangoproject.com/en/2.1/topics/forms/formsets/), to be able to upload multiple files at once. So the code will roughly look like this

{% for form in formset %}
    <input type="file" name="{{form.name}}" id="{{form.id_for_label}}" />
    {{form.file.errors}}
{% endfor %}

Now each file will have some unique id, as you will see when you use formset. to populate data in the table, you need to listen for file change event and change the table.

<td data-name="fileUniqueId1"></td>
<td data-name="fileUniqueId2"></td>
<td data-name="fileUniqueId3"></td>

$("form input[type='file']").change(function(e){
    var fileId = e.target.id;
    $("table td[data-name='"+ fileId +"']").text(e.target.files[0].name);
});