Edun Rilwan
Posted on May 12, 2024
It is a common feature in most web apps to prompt users to upload files or documents. These files include image files (.jpeg, .jpg, .png) or other document files like PDFs, audio files (.mp3), etc.
Django, a very popular and powerful web framework in Python provides built-in methods and utilities that enables seamless upload and storage of files in web applications.
In Django, there are 3 ways to accept media uploads from users. They include the following:
Django ModelForms
Django Forms
Pure HTML forms
In this tutorial, you will learn how to handle media uploads with Django ModelForms using a local storage. Django's ModelForm provides a convenient and faster way to create forms in Django. They are also very customizable.
By the end of this tutorial, you would have learned the following:
- How to receive media files via a ModelForm
- How to handle and save the received file object
- How to display saved image files on a web page
- How to make saved files available for download by users.
Project requirements
Python: You need a Python interpreter installed on your computer. Preferably python>=3.8
Django: The latest version of Django is required.
Create a new virtual environment using the virtualenv
package in Python:
virtualenv env
Use the command below to activate the virtual environment:
Windows:
env\Scripts\activate
Linux/macOS:
env/bin/activate
Install Django in the new virtual environment:
pip install Django
Note: To confirm your virtual environment (VE) is activated, check to see the name of your VE in a bracket like the one below:
(env) >>>
Getting started with Django file upload
You need to create a new Django project and app to learn how Django handles media uploads.
Create a Django project
Follow the steps below to create a Django project:
a. Open your terminal(check that your VE is activated).
b. Run the command below to create a Django project
django-admin startproject my_project
c. Enter the command below to move into the new my_project folder
cd my_project
Next step is to create an app.
Create a Django app
Run the command below in the terminal to create an app named file_upload
python manage.py startapp file_upload
Open the settings.py file in your project folder and add the app to the INSTALLED_APPS list as seen below:
#my_project/settings.py
INSTALLED_APPS = [
...
"file_upload"
]
Django MEDIA ROOT and MEDIA URL
MEDIA_ROOT and MEDIA_URL variables are crucial in handling media uploads in a local filesystem storage. They provide a way of accessing and storing saved files in a Django app.
Django MEDIA ROOT
MEDIA ROOT refers to the root folder where all uploaded files are stored in a Django web app. It refers to the folder where all files can be accessed from.
How to set up a MEDIA ROOT
To set up a MEDIA ROOT, do the following:
a. Create a new folder named uploads in your project folder
#file_arrangement
my_project
\__ my_project
\__ file_upload
\__ uploads
b. Open settings.py file and include the following line of code in it:
MEDIA_ROOT = BASE_DIR / "uploads"
This setting instructs Django to save uploaded files to the uploads folder within your project, that is BASE_DIR.
BASE_DIR is a variable automatically set by Django. It contains the file path to your current project, which is also known as the base directory.
Django MEDIA URL
MEDIA URL refers to the root URL that renders user-uploaded files present in the MEDIA ROOT of a web app.
For example, if you uploaded an image file titled example.jpg, it is rendered on the web via a url like the one below:
https://mysite/[MEDIA_URL]/[MEDIA_ROOT]/images/example.jpg
The URL above is analyzed as follows:
- mysite is the domain name of your website.
- media_url is the base/root url for uploaded media.
- media_root is the root folder for uploaded media.
- images is another folder inside the MEDIA ROOT that stores image files only
- example.jpg is the file name.
How to set up a MEDIA URL
a. Open your project's settings.py file and add the code below:
MEDIA_URL = "files/"
b. Open the urls.py file in your project folder
c. Add the following import statements:
from django.conf import settings
from django.conf.urls.static import static
d. Write the following code below the urlpatterns list in the urls.py file:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In the steps above, a MEDIA URL, named files is created. This root url for media uploads is finally added to the list of URLs.
Create a Database Model
The next step is to create a database model named Uploads. This model will have three field types which includes: A Charfield, FileField and an ImageField. Follow the steps below to create the Uploads
model:
a. Go to the models.py file in your app
b. Create a simple database model titled Uploads
from django.db import models
# Create your models here.
class Uploads(models.Model):
caption = models.CharField(unique=False, null=False, blank=False, max_length=20, default="An image")
file_field = models.FileField(upload_to="files", null=False, blank=False)
image_field = models.ImageField(upload_to="images", null=False, blank=False)
The functions of each field are listed below:
CharField
stores textual data.
FileField
stores files such as PDFs, docx, etc.
ImagField
stores image files.
The FileField
and ImageField
have an upload_to
argument. This refers to a new folder inside your project's MEDIA ROOT where the content of each file field will be stored. It is created automatically when a file is uploaded to each field.
Run migrations for the database
Run database migrations via the steps below:
a. Open the terminal and run this command
python manage.py makemigrations
b. Run the command below to add the migrations to a file
python manage.py migrate
Migrations help to track changes made to the database.
Build a ModelForm
Follow the steps below to build a ModelForm:
a. Create a forms.py
file in your app folder
my_project
\___ file_upload
\___ ...
\___ forms.py
b. Add the code below to the file:
from django import forms
from .models import Uploads
class FileUploadForm(forms.ModelForm):
class Meta:
model = Uploads
fields = "__all__"
The code above creates a ModelForm
based on the structure of the Uploads model. The __all__
method means that the form should contain all the fields in the database model.
Create a view for media uploads
Follow the steps below to create a view function:
a. Open the views.py file
b. Add the code below
from django.shortcuts import render, redirect
from .forms import FileUploadForm
from .models import Uploads
# Create your views here.
def handle_upload(request):
form = FileUploadForm()
if request.method == "POST":
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return render(request, "form.html", context={"form": form})
The view function renders the ModelForm through a form.html
file that will be created in the next step.
This view also accepts POST requests from the ModelForm when the user submits their uploads. It verifies that there are no form errors before saving the user input.
It is necessary to include the request.FILES
and request.POST
dictionary in the form class for each POST request.
POST requests are usually sent with a requests.POST
dictionary. When files are involved, a request.FILES
dictionary is added.
Uploaded files are stored temporarily in a request.FILES
dictionary. Each key in this dictionary holds the data of a particular file field in the form submitted.
For example, if you created a form with a FileField named "images", you can access the file data in your views function via the code below:
request.FILES['images']
Create the homepage file
You need to create an HTML file named form.html
that'll render the form. Follow the steps below to do create a web page:
a. Create a new folder named templates in your project
my_project
\___ my_project
\___ ...
\___ templates
\___ ...
b. Create a new HTML file named form.html
inside this folder
c. Add the code below inside this file
<head>
<meta charset="UTF-8">
<title>Forms practise</title>
</head>
<body>
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit">
</form>
</body>
The HTML code above displays the form to the user through form.as_p
, while the {% csrf_token %}
enables secured transfer of form data
The enctype="multipart/form-data"
variable enables the form to send file data.
Finally, you need to register the templates folder with Django so it can access it.
To do this, open the settings.py
file in your project folder and add the code below to the TEMPLATES
list in this file:
TEMPLATES = [
{
'...',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'...'
}
]
Configure app urls.
The next step is to bind the view function to a url. Follow the steps below to do this:
a. Open the urls.py file in your app folder
my_project
\___ file_upload
\___ ...
\___ urls.py
\___ ...
b. Add the code below to this file
from django.urls import path
from file_upload import views
urlpatterns = [path("", views.handle_upload, name="home")]
c. Open the urls.py file in your project folder
my_project
\___ my_project
\___ ...
\___ urls.py
\___ ...
d. Register your app URLs to the urlpatterns list in your project.
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
"...",
path("", include("file_upload.urls")),
]
Test the app
a. Run the command below in your terminal
python manage.py runserver
b. Click on the link to open the web page
c. Click on the _Choose file _button to upload your files.
c. Enter a caption of your choice.
d. Submit the form.
e. Proceed to the upload
folder, you would see two new folders named files
and images
.
In the files folder, you would see the document you uploaded.
In the images folder, you would see the image file you uploaded.
Display user uploads
In most cases, users would need access to their files. You can display media uploads to users using a simple .url
attribute. The steps below show you how to display uploaded files to users:
a. Open the views.py file
b. Update the view function to contain the Uploads
model and pass it to the render function.
from django.shortcuts import render, redirect
from .forms import FileUploadForm
from .models import Uploads
# Create your views here.
def handle_upload(request):
form = FileUploadForm()
uploads = Uploads.objects.all()
if request.method == "POST":
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect("home")
return render(request, "form.html", context={"form": form, "uploads": uploads})
c. Proceed to the form.html
file
d. Add this code below the form in the HTML file
{% for media in uploads %}
{% if media %}
<div style="margin: 20px 0px;">
<img src="{{ media.image_field.url }}" height="200px;" width="200px;">
<p>{{ media.caption }}</p>
<p>Download your file <a href="{{ media.file_field.url }}">here</a></p>
</div>
{% endif %}
{% endfor %}
e. Wait for the server to reload
f. Open the browser and refresh the web page
This process simply queries all records in the Uploads model, adds it to the context dictionary so it can be accessed and used in the HTML file.
The image you uploaded will be displayed on the web page and your document will be available for download. Here is an example below:
Conclusion
Leveraging Django's ModelForms for file uploads simplifies the process of handling user-submitted files. Whether it's for pictures, documents or any other type of file, ModelForms provides an efficient and structured way to manage file uploads in Django.
Frequently asked questions (FAQs)
What type of media files can be uploaded in Django?
You can upload files of different sizes and formats in Django. However, if you are using a local file-storage, you will get to a point where the memory gets full and you will need to use a cloud service like AWS, Google clouds, etc.
An overloaded memory will affect site performance.
How can I secure media uploads in Django?
There are different security measures you can apply to media uploads in Django. They include:
- Verifying the file formats before saving them. That is, by checking the file extensions, such as .png, .jpg, .pdf, etc. to be sure they are safe
- Sometimes, reading file metadata before saving is also important. However, you may need to use third-party Python libraries to like Pillow to implement this.
How to handle media uploads in a production environment?
It is not advisable to use a local file storage in a production environment. This is because such implementation may have security implications on stored files.
Using cloud services enhance application performance and provide more flexibility and security to uploaded files.
Can I resize or manipulate uploaded images in Django?
Yes, you can.
Before saving an uploaded file, you can get the file object from the request.FILES
dictionary and use it directly with a file manipulation library like Pillow, OpenCV, etc. in Python.
After editing the image, you can then save it to a file of your choice.
How does the Django Filesystem work?
When a user uploads a file in Django, the Django filesystem has two handlers that handles file uploads. For small files, they are saved to memory using the (handler) handler while the (handler) handler handles large files by saving them to a temporary file.
What happens when I delete saved files in Django?
Deleted files are immediately removed from the MEDIA ROOT of your app. Therefore, trying to access a deleted file through the .url
attribute will throw an error.
Posted on May 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.