Home Django How to upload files in Django

How to upload files in Django

File uploads are important for a healthy Django web project. The same reason you attach files while sending emails is the same reason you need to have this functionality implemented in your Django projects. Also, you might be interested in creating an email app based on Django. What are the odds? This article seeks to explore the Ins and Outs of file uploads under Django.

You will learn how to set up your Django projects to implement file uploads from both the front and back-end. Before we take another step, it is important to familiarize yourself with setting up a Django project skeleton. The latter link not only takes you through the setup of your Django project but also explains the project structure convention used in Django.

The concept of file uploads in Django is quite simple. When a file upload session is initiated by some user, a document called request.FILES handles the file upload data. It is more of a request object, and Django has several request objects which you can look at if you have time to explore. The functional purpose of this request object document is to narrate the Django file storage rules. These rules apply to how your uploaded files will be stored in the system memory and the computer disk.

Some notable preconfigurations

Your main project’s settings.py file needs to have some additional configurations which support file uploads. Add the following two lines at the bottom of this file.

settings.py

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

At the top of this file, we need to import os as it is defined through MEDIA_ROOT. Failing to import it will lead to a NameError when you start your development server. Add the following import declaration at the top of your settings.py file.

settings.py

Import os

With these settings, your Django development server will create a media directory alongside the project’s main directory and app director. It is this media directory that will contain the user-uploaded files. We also need to inform the project’s main URL or url.py of the whereabouts of these defined media configurations. Your main urls.py file should have the following configurations.

urls.py

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
	#defined Django project URL patterns
]

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

Performing a simple file upload

Since we are dealing with file uploads, you might be anticipating us defining a Django model that will be used to store the uploaded files. Your instincts are correct. But we are going to implement file uploads through model forms in the next section of this article. Reason? We want first to demonstrate how you can also upload and save files through FileSystemStorage. We found it necessary to implement this file upload approach as a warm-up session.

Inside your app’s templates folder, create the following html file.

my_simple_upload.html

{%  extends 'base.html' %}  
{%  load static %}
{% block content %}
 <form method="post" enctype="multipart/form-data">
	{% csrf_token %}
	<input type="file" Name="myfile">
	<button type="submit">upload</button>
 </form>
     {%  if file_upload_url %}
      <p> Your file was successfully uploaded at: <a href="{{ file_upload_url }}">{{ file_upload_url }}</a></p>
     {% endif %}
      <p><a href="{% url 'home' %}">Return to Home Page</a></p>
{% endblock %}

Your base.html file could be represented in the following manner.

base.html

<!DOCTYPE html>
<html>
<head>
<title>How to Upload Files in Django</title>
</head>
<body>
    <p>Brandon Jones' Django File Uploads Tutorial<p/>
	{% block content %}
	{% endblock %}
</body>
</html>

Now let us create the views that map to my_simple_upload.html file.

views.py

from django.shortcuts import render
from django.conf import settings
from django.core.files.storage import FileSystemStorage 

def home_page(request):
	return render(request, 'home_page.html')
def simple_file_upload(request):
	if request.method == 'POST' and request.FILES['my_file']:
		my_file = request.FILES['my_file']
		fs = FileSystemStorage()
		filename = fs.save(my_file.name, my_file)
		file_upload_url = fs.url(filename)
		return render(request, 'my_simple_upload.html', {'file_upload_url': file_upload_url})
	return render(request, 'my_simple_upload.html')

We also need to have a simple url configuration that will help us map our defined views to the web browser.

urls.py

from django.contrib import admin
from django.urls import path
from file_uploads import views

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
	path('admin/', admin.site.urls),
	path('', views.simple_file_upload, name='home'), 
]

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

Depending on how you defined or named your Django app, remember to include it in your project’s settings.py file as depicted below.

settings.py

# application definition
INSTALLED_APPS = [
	#...
	'file_uploads',
]

It is now time to see our code in action. Start the development server and access the following url:

http://127.0.0.1:8000

My landing page looks like the following screenshot. Do not worry about the page styling. If you want to add some CSS to this page, consider the article guide we have on Django bootstrap tutorial.

Landing page for how to upload files in Django tutorial
Landing page for how to upload files in Django tutorial

Now if I go ahead and upload any file, the following will be the resulting web interface.

Resulting web page after a user uploads a file in Django tutorial
Resulting web page after a user uploads a file in Django tutorial

As you have noticed, this Django file upload functionality lets you upload a file of any extension whether it is an image, Word, or PDF document.

Using model forms for file uploads

This approach is highly recommended for Django file uploads. It is a convenient way of validating your form data. Other advantages of this approach include the ability to deal with filename conflicts and the automatic buildup of an absolute path that points to the uploaded file’s storage location.

To kick-start this next tutorial, we are going to learn some basic file upload rules and implementation. Inside your created Django app directory, you need to create or have a forms.py file alongside the default views.py, admin.py, and models.py files. This python file will document the FileField that is responsible for facilitating file upload through a form field. Since we are introducing the use of Forms and Models in this section, we need to start defining them.

Your models.py file should resemble the following:

models.py

from django.db import models
#create your models here
class DocumentUploads(models.Model):
	description = models.CharField(max_length=255, blank=True)
	document = models.FileField(upload_to='mydocuments/') 
	uploaded_at = models.DateTimeField(auto_now_add=True) 

The forms.py file we are going to use should be as simple as this one.

forms.py

from django import forms
from file_uploads.models import DocumentUploads
class UploadMyFile(forms.ModelForm):
	class Meta:
		model = DocumentUploads
		fields = ('description', 'document',)

This forms.py file will be communicating with a views.py file on your Django app directory. The views.py file is responsible for the views or the logic code your app is trying to represent. This views.py file then communicates with the urls.py file, which maps your views on a web browser. Django has a default urls.py file under the main project directory. You can define a urls.py file inside each of your app’s directories, then point them to the main urls.py file. This approach makes your project apps modular and flexible.

We now need a model view. Add the following view function to your views.py file.

views.py

from django.shortcuts import redirect 
from file_uploads.forms import UploadMyFile
#the above import should be on top of the views.py file
def model_form_upload(request):
	if request.method ==  'POST':
		form = UploadMyFile(request.POST, request.FILES)
		if form.is_valid():
			form.save()
			return redirect('model_forms')
	else:
		form = UploadMyFile()
	return render(request, 'my_simple_model_upload.html', {'form': form})

We need to connect this view to the main or root URLs file. Add the following code to your urls.py file.

urls.py

path('models/upload', views.model_form_upload, name='model_forms')

The HTML file for holding this form should look similar to the following:

My simple model upload

{% extends 'base.html' %}
{% block content %}
   <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
         {{ form.as_p }}
        <button type="submit">Upload File</button>
   </form>
   <p><a href="{% url 'model_forms' %}">Return to Home Page</a></p>
{% endblock %}

Back to the forms.py file. We defined and linked to our Django views. Django’s view handling uses requests.FILES to communicate with the form file data. Think of it as a data structure dictionary that links each form’s FileField or ImageField with a unique key. In this case, request.FILES[‘file’] becomes the ideal logical approach for accessing form data.

You should get a clear picture of this concept from its implementation in the views.py file. There are rules that request.FILES operates under. For instance, the defined form’s method has to be POST for it to hold uploaded data or files. Another important form attribute that must exist is enctype=”multipart/form-data”. The absence of this condition will leave the request.FILES empty.

The next step is to make the necessary migrations since we are using models. Run the following commands on your terminal.

(m_env)$ python3 manage.py makemigrations
(m_env)$ python3 manage.py migrate

It is now time to experience the model forms file upload snippets we have created. Turn to your browser while the Django development server is still running and access the following URL.

http://127.0.0.1:8000/model/uploads

The landing page from my end looks like the following screenshot.

Landing page for using Form Models to upload files in Django

Let us upload a file and see how the page will respond.

Populated Form Models page for Django files uploads
Populated Form Models page for Django files uploads

The newly defined view function to handle the logic of our model forms has a redirect function. It clears the form for another submission once the one in front of the queue is successfully submitted. The upload_to functional argument helps you define a specific target folder for storing your uploaded files. This target folder will be under the media folder created from the configurations we earlier placed in the settings.py file.

Final Note

File uploading is an interesting functionality for completing a project master piece. Django creates a soft learning curve for file uploads. Based on this tutorial, you can challenge yourself to upload files from the Django admin side.

Because of the Django file upload rules, we also have to note a few precautions. Not all users that will be uploading files through your Django platform come with good intentions. Some uploaded file contents are not trustworthy. This issue forces the admin of this site to consider adhering to some Django file uploads security guidelines.

You may also like

Leave a Comment

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More