Django Multiple File Upload

Photo by Jefrey Betts

There are several practices to implement a file upload feature like this. This article describes how to implement the uploader using a jQuery plugin, jQuery File Upload that communicates with the server using AJAX and also takes care of the cross browser compatibillity.

Dependencies

Here is what we are going to use:

Django 1.8

jQuery Base dependency of the file upload plug-in.

jQuery File Upload That’s the file upload plagin

Bootstrap This is optional. Just so the example has a good looking interface

 

Settings

In Django to deal with files we need to add the relevant MEDIA settings:

# Media settings MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Another setting we need in django urls file for testing in the development environment is the following:

from django.conf.urls import url, include 
from django.contrib import admin 
from django.conf.urls.static import static 

urlpatterns = [ url(r'^admin/', admin.site.urls),

# this is our photo upload page url url(r'^gallery/', include('photo_upload.urls')), ] 
# 
#  set this for local testing if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Add dependencies to our project. This is an example of hwo our base.html could look like:

{% load static %} 
<!DOCTYPE html> 
<html lang="en"> 
   <head> 
      <meta charset="utf-8"> 
      <meta name="viewport" content="width=device-width, initial-scale=1"> 
      <title>{% block title %}Photos Library - Simple is Better Than Complex{% endblock %}</title> 
      <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet"> 
   </head> 
   <body> 
   <div class="container"> 
      {% block content %} 
      {% endblock %} 
   </div> 
   <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script> 
   <script src="{% static 'js/bootstrap.min.js' %}"></script> 
   {# plugin scripts #} 
   <script src="{% static 'js/jquery-file-upload/vendor/jquery.ui.widget.js' %}"></script> 
   <script src="{% static 'js/jquery-file-upload/jquery.iframe-transport.js' %}"></script>
   <script src="{% static 'js/jquery-file-upload/jquery.fileupload.js' %}"></script> {# our photo upload page script #}
   <script src="{% static 'js/jquery-file-upload/photo-upload.js' %}"></script> 
   </body> 
</html>

 

jQuery File Upload is a  widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. In this example we are only going to use some of it's possibilities but it worths further exploring so after finishing this tutorial my suggestion is to go ahead and check jQuery File Upload Documentation

 

Example: Gallery Django Application

Assuming than we created a Django application, called gallery, to build our photo upload example lets create a Model for our photos:

# Create your models here.
class Photo(models.Model):
   image = models.ImageField(upload_to='photos/')
   uploaded_at = models.DateTimeField(auto_now_add=True)

 

* ImageField requires installing Pillow locally

 

And then create the form using ModelForm:

from django import forms
from .models import Photo

class PhotoForm(forms.ModelForm):
   class Meta: model = Photo fields = ('image', )

You've allready set our rout:

... url(r'^upload/', views.PhotoUploadView.as_view(), name='photo_upload'), ...

Now let's add a view to process our photo upload. Bellow we adding a simple view using Django View Class Based View:

from django.shortcuts import render from django.http import JsonResponse from django.views import View from .forms import PhotoForm from .models import Photo class PhotoUploadView(View): def get(self, request): gallery = Photo.objects.all() return render(self.request, 'upload.html', {'gallery': gallery}) def post(self, request): form = PhotoForm(self.request.POST, self.request.FILES) if form.is_valid(): photo = form.save() data = {'is_valid': True, 'name': photo.image.name, 'url': photo.image.url} else: data = {'is_valid': False} return JsonResponse(data)

 

On the above example we are using a Class Based View PhotoUploadView(View)  to handle GET and POST methods to precess requests. When we upload photos (POST) we call form.save() to create a Photo instance and save our files.

jQuery File Upload plugin will handle the rest in the client side. Lets add a template to display our photo upload widjet:

<div class="panel panel-default"> <div class="panel-body"> <p>Photo Upload Example</p> <!-- Drop Zone --> <div class="well text-muted text-center upload-drop-zone" id="drop-zone" <h3>Drop Photos Here to Upload</h3> <h4 align="center">Or</h4> <button type="button" class="btn btn-primary js-upload-photos"> Select Files </button> <input id="fileupload" type="file" name="images" multiple style="display: none;" data-url="{% url 'gallery:photo_upload' %}" data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'> <div id="file_upload_message"></div> </div> <!-- progress Modal --> <div class="modal fade" id="modal-progress" data-backdrop="static" data-keyboard="false"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 id="file_upload_message" class="modal-title">Uploading...</h4> </div> <div class="modal-body"> <div class="progress"> <div class="progress-bar progress-bar-success" role="progressbar" </div> </div> </div> </div> </div> </div> </div> </div>

First we need to hook our button,  js-upload-photos,   to open the file explorer window.

Next we need to add an input file

Finally lets add the page script. Add the folowing code to our costom JS file, photo-upload.js and we'll explain afterwords:

function setFileUploadMessage(msg) { $("#file_upload_message").show(); $("#file_upload_message").text(msg); } $(function () { $(".js-upload-photos").click(function () { $("#fileupload").click(); }); $("#fileupload").fileupload({ dataType: 'json', singleFileUploads: false, // default true sequentialUploads: true, start: function (e) { $("#file_upload_progress").show(); setFileUploadMessage("Uploading files..."); $("#modal-progress").modal("show"); }, stop: function (e) { $("#modal-progress").modal("hide"); }, progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); var strProgress = progress + "%"; $(".progress-bar").css({"width": strProgress}); $(".progress-bar").text(strProgress); }, fail: function (e, data) { setFileUploadMessage("Upload error? " + data.errorThrown + " ... " + data.textStatus); }, progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); var strProgress = progress + "%"; $("#modal-progress .progress-bar").css("width", progress+"%"); $(".progress-bar").text(strProgress); }, done: function (e, data) { //show list of uploaded images here } });

 

Trigger the input to open the file upload dialog with a click event. Our file upload view returns JSON data. Use plugins functionality to start the upload - show progress bar - show Drag n Drop - finally upload files and display a list of them

 

This are just some of jQuery File Upload  features. There are a bunch of abilities for this plugin and it is a matter of configuration and playing with the plugin. For more details please refer to the official documentation for the  jQuery File Upload Plugin

 

 

{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{% block title %}Photos Library - Simple is Better Than Complex{% endblock %}</title> <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet"> </head> <body> <div class="container"> {% block content %} {% endblock %} </div> <script type="text/javascript" src="{% static 'jquery/fileupload/js/jquery.ui.widget.js' %}"></script> <script type="text/javascript" src="{% static 'jquery/fileupload/js/jquery.fileupload.js' %}"></script> <script src="{% static 'js/bootstrap.min.js' %}"></script> </body> </html>

Comments

======= >>>>>>> master

+30 211 790 2526

Find me

kabardi.cat@gmail.com