Implementing Multiple File Uploads in Django
Published: 2023-07-18 19:32:30


In today's modern web applications, the ability to upload and manage multiple files has become increasingly important. Whether it's allowing users to upload multiple images, documents, or media files, supporting numerous file uploads enhances the user experience and enables richer functionality. In this article, we will explore how to implement the feature of multiple file uploads in Django, a powerful and widely-used web framework.

Django provides a solid foundation for handling file uploads, and by leveraging and extending its capabilities, we can create a seamless and efficient experience for users interacting with our applications. By implementing multiple file uploads, we empower users to submit multiple files simultaneously, streamlining their workflows and saving time. This feature is particularly valuable in scenarios where users need to upload multiple images for a gallery, submit multiple documents for a project, or attach multiple files to a form.

This article will dive into the various aspects of implementing multiple file uploads in Django. We will cover the configuration of file upload handling, creating the necessary views and forms, managing file storage and organization, displaying and accessing the uploaded files, performing validations, and addressing security considerations.

Let’s hop on this and acquire the knowledge and skills we need to enhance our web applications and provide with a seamless file upload experience for our users.


## Why is Multiple File Upload Important?
Identifying the specific use case for multiple file uploads is crucial in determining the need and importance of implementing this feature in a web application. Here are a few common use cases where supporting multiple file uploads is particularly valuable:

- Media Galleries: Applications that involve displaying collections of images, videos, or other media often require the ability to upload multiple files at once. This use case is relevant for platforms such as photo-sharing websites, content management systems, or e-commerce sites that allow users to upload multiple product images.

- Document Management: Applications that deal with document management, such as project management tools or document collaboration platforms, benefit from multiple file upload functionality. Users can upload multiple documents or files related to a project or task, making it easier to organize and share information.

- Form Submissions: Web applications with complex forms often require users to attach multiple files during submission. For instance, job application forms may ask for resumes, cover letters, and additional documents. By supporting multiple file uploads, users can submit all the required documents simultaneously, simplifying the process and improving the user experience.

- Attachments and File Sharing: Applications that involve file sharing, such as email clients, messaging platforms, or file storage services, commonly need support for multiple file uploads. Users can attach multiple files to emails, share them with others, or upload multiple files to cloud storage accounts.

- Bulk Data Import: In certain applications, users may need to import large amounts of data in the form of files. For example, an e-commerce platform might allow merchants to import product data using a CSV file. Supporting multiple file uploads streamlines the data import process and improves efficiency.

- Content Creation and Publishing: Content management systems, blogging platforms, or multimedia platforms often require the ability to upload multiple files simultaneously. Users can upload images, videos, or other media files to create and publish rich content.

- Data Backup and Restore: Applications that involve data backup or restore functionality can benefit from multiple file uploads. Users can select and upload multiple files for backup or restore operations, simplifying the process and enabling efficient data management.

Multiple file uploads come in handy in numerous ways for applications and software with different goals and scopes to simplify processes, save time and increase productivity.

## Prerequisites
To get the most out of this article, it is advisable you;

- Have a good working knowledge of the Python Programming Language
- Are comfortable using the Django Web Development Framework
- Have Basic knowledge of HTML/CSS
- Have Python 3.10+ installed
- Have Django 4.0+ installed
- Have Pillow installed

## About our MiniProject for Multiple File Uploads
To demonstrate practically, how to implement multiple file uploads in Django, we will build this MiniProject, which will contain one app; the MiniApp.

What this App does is, it enables you to upload multiple files (for this article, we will be uploading images) at a go and then it redirects you to a page where you can see all the images you’ve uploaded.

Simple and sweet, Let’s jump on it!


## Step 1: Setting up the Django Application
To start, we will set up a basic Django application and start a new Django project as follows;

```
django-admin startproject MiniProject
```

Now in the new MiniProject directory create a new App as;

```
python manage.py startapp MiniApp
```
Next up, in the MiniProject’s Settings.py file, we add the new MiniApp;

```
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'MiniApp',
]
```

Now, a few more set-ups, in the MiniProject folder, create two new folders and name them static, and templates respectively;



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ad4k0oy0lgoyfxn5llwf.png)

Now connect the “templates” folder, where we will store our HTML templates, to the Django template engine in the Settings.py file;

```
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

## Step 2: Configuring static file serving for uploaded files and setting up media file storage options in Django settings
Configuring static file serving for uploaded files in Django is essential for the proper handling and accessibility of the uploaded files within our web application.

To this, we set up a STATICFILES_DIR and STATIC_ROOT in addition to the STATIC_URL already present in the Setting.py file;

```
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]
STATIC_ROOT = os.path.join(BASE_DIR, 'assets')
```

To add set up the media file storage of the app, we will add a MEDIA_URL and MEDIA_ROOT in the Settings.py file;

```
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
```

## Step 3: Create a model for file upload and the ModelForm

Now we will set up our model class for the file upload in the MiniApp’s models.py;

```
from django.db import models

class Image(models.Model):
	pic = models.FileField(upload_to='MiniApp_Images')

```

For the ModelForm, which will be used to upload the files from the html templates
Create a forms.py file in the MiniApp;

```
from django import forms
from .models import Image

class ImagesForm(forms.ModelForm):
	pic = forms.FileField(widget = forms.TextInput(attrs={
            "name": "images",
            "type": "File",
            "class": "form-control",
            "multiple": "True",
        }), label = "")

	class Meta:
		model = Image
		fields = ['pic']
```

## Step 4: Set up HTML Templates to be used

We will create 2 html templates index.html and upload.html, the former is to view the output of our file uploads and the latter is to upload the files themselves.


Index.html;

```
{% load static %}
<!DOCTYPE html>
<html>
<head>
  <link   href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
      rel="stylesheet" 
      integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
      crossorigin="anonymous">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style type="text/css">
    .container{
      margin-top: 5rem;
      margin-left: auto;
      margin-right: auto;

    }

    .card{
      margin: auto;
    }
  </style>
  <title>Mini App</title>
</head>
<body>
  <div class="container row">

    {% for image in images %}
      <div class="card col-md-4" style="width: 18rem;">
        <img src="{{image.pic.url}}" class="card-img-top" alt="...">
        <div class="card-body">
          <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
        </div>
      </div>
    {% endfor %}

  </div>

</body>
</html>
```

Upload.html;

```
<!DOCTYPE html>
<html>
<head>
	<link 	href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
			rel="stylesheet" 
			integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
			crossorigin="anonymous">

	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<style type="text/css">
    .container{
      margin-top: 20rem;
    }
  	</style>
	<title>Multiple File Uploads</title>

</head>
<body>

	<div class="container center">

		<form method="POST" enctype="multipart/form-data">
			{% csrf_token %}
			<div class="mb-3">
			  <label for="formFile" class="form-label">Upload Files Here</label>
			  {{form}}
			</div>

			<button type="submit" class="btn btn-outline-primary ">Submit</button>
		</form>
		
	</div>
</body>
</html>
```

## Step 5: Create necessary views and URL routes

We will now create the views for the file upload and viewing in the MiniApp’s 

Views.py;

```
from django.shortcuts import render, redirect
from .forms import ImagesForm
from .models import Image

# Create your views here.
def index(request):
	images = Image.objects.all()
	context = {'images': images}

	return render(request, "index.html", context)

def fileupload(request):
	form = ImagesForm(request.POST, request.FILES)

	if request.method == 'POST':
		images = request.FILES.getlist('pic')

		for image in images:
			image_ins = Image(pic = image)
			image_ins.save()

		return redirect('index')

	context = {'form': form}
	return render(request, "upload.html", context)

```

Next, we will create a new urls.py file in the MiniApp’s directory and create the necessary URL routes;

```
from django.urls import path
from . import views

urlpatterns = [
	path('', views.index, name = 'index'),
	path('upload', views.fileupload, name = "File_Uploads")
]
```

For the MiniProject’s urls.py;

```
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

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

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

## Step 6: Make Database Migrations, Migrate, and Runserver to test.

In this 6th and final step, we first will make database migrations;

```
python manage.py makemigrations
```

Then we will migrate;

```
python manage.py migrate
```

Last but not least we run our server to test the code;

```
python manage.py runserver
```

output;

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmtc1a5kfbff6zv761zc.gif)

## Final Thoughts
Overall, supporting multiple file uploads enhances the user experience, improves productivity, and expands the capabilities of web applications. It provides flexibility, convenience, and efficiency, allowing users to work with multiple files seamlessly and empowering them to accomplish tasks more effectively.

Embrace this feature, experiment with different use cases, and continue building exceptional Django applications that deliver a superior user experience.

To further explore this feature, you may find the following links helpful;

[Django Docs on File Uploads](https://docs.djangoproject.com/en/4.2/topics/http/file-uploads/#:~:text=If%20you%20want%20to%20upload,also%20have%20to%20subclass%20FileField%20.)
[Github Repo of the MiniProject](https://github.com/Veino/MiniProject-How-to-Implement-Multiple-File-Uploads-in-Django)
[Django Support Community](https://www.djangoproject.com/community/)