Upload multiple images to your Django app using Dropzone Js
Tags: javascript, django, webdev
Published: 2021-08-18 08:09:05

Hello guys it's been a minute! I was on a small break but now am back and in this tutorial we are going to learn how we can upload multiple images to a Django back end. By default the Django behavior is that you select a single image and upload it to the server then repeat which begs the question isn't that a time consuming and tedious process, say if we have 1000 images?  It is.
Fortunately, there is a tool that can help us go around this problem, a JavaScript library called [Dropzone](https://www.dropzonejs.com/) . Let's not waste more seconds, let's get into it!
###PROJECT SETUP
Let's quickly navigate to our desktop directory and bootstrap the back end. 
```
cd ~/Desktop

mkdir django_dropzone && cd django_dropzone

virtualenv env

source env/bin/activate

pip install django

django-admin startproject mysite .

python manage.py startapp core 
```

Next add `core` to the list of installed apps in `settings.py`. 
While there also update the templates section as follows:
```python
import os

'DIRS': [os.path.join(BASE_DIR, 'templates')],
```
Then also update the static settings like so:
```python
STATIC_URL = '/static/'
if DEBUG:
    STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
else:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
```
###IMAGE MODEL
We have set up our `settings.py` and it's good to go. Move to `core/models.py` and add the following code:
```python
from django.db import models

# Create your models here.

class Image(models.Model):
    image=models.ImageField(upload_to='images/')
    date = models.DateTimeField( auto_now_add=True)

    class Meta:
        ordering=['-date']
        
    def __str__(self):
        return str(self.date)
```
Go ahead and `makemigrations` then `migrate` to apply the changes to the db. 
Next we go the the `views.py`. Write the following code to it.
```python
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from .models import Image
# Create your views here.

def home(request):
    images=Image.objects.all()
    context={
        'images':images
    }
    return render(request, 'index.html', context)

def file_upload(request):
    if request.method == 'POST':
        my_file=request.FILES.get('file')
        Image.objects.create(image=my_file)
        return HttpResponse('')
    return JsonResponse({'post':'fasle'})
```
Next create `core/urls.py` and add the following code to it:
```python
from django.urls import path
from . import views
urlpatterns = [
    path('', views.home, name='home'),
    path('upload/', views.file_upload),
]
```
To finalise the Python part, add the following code to the project's `urls.py`
```python
rom django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('core.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
```

###DROPZONE SETUP
We are done with the logic let's do the UI stuff. Create a folder called `static` and in it create two files:
```
touch static/main.js

touch static/style.css

```
Add the following code to `main.js`:
```js
Dropzone.autoDiscover=false;
const myDropzone= new Dropzone('#my-dropzone',{
    url:'upload/',
    maxFiles:5,
    maxFilesize:2,
    acceptedFiles:'.jpg',
})
```
And the following to `style.css`:
```js
body {
    background-color: #f8f8f8 !important;
}

.dz {
    border: dashed !important;
    background-color: #ccc !important;
    border-radius: 10px !important;
}

.dz:hover {
    background-color: aliceblue !important;
}
```
Next create a folder called `templates` and in it create two files:
```
touch templates/base.html

touch templates/index.html

```
Add the following code to `base.html`
```js
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <!-- Font awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <!-- custom css & js -->
    <link rel="stylesheet" href="{% static 'style.css' %}">
    <script src="{% static 'main.js' %}" defer></script>

    <script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
    <link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">


    <title>Drag and Drop Django| {% block title %}{% endblock title %}</title>
  </head>
  <body>
    <div class="container mt-3">
        {% block content %}
        {% endblock content %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
  </body>
</html>
```
And the following to `index.html`:
```js
{% extends 'base.html' %}

{%block content%}
<h6>UPLOAD MULTIPLE IMAGES NOW</h6>
<br>
<form enctype='multipart/form-data' action="upload/" method='POST' class="dropzone dz" id="my-dropzone" >
    {% csrf_token %}
    <div class="fallback">
      <input name="file" type="file" multiple />
    </div>
</form>
{%endblock%}
```
###SPIN UP THE SERVER
Now go to the terminal and:
```
python manage.py runserver
```
Check the browser and upload images, be sure to select multiple. 

![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vwv1qnrc5rp5sr9x8rq3.png)
and
![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1yihpeitc8kagpd46jvf.png)
###MISSION SUCCESS
Yeah that should do it for this article. Thanks for keeping me company and coding along. You can grab the source code of this project [here](https://github.com/nicksonlangat/django-dropzone)
You can connect with me on [LinkedIn](https://www.linkedin.com/in/langat-nickson-26081119a/) and on [Twitter](https://twitter.com/NicksonLangat20)
Cheers and see you next time!