File uploading is a common feature in many web applications. Whether you’re building a resume submission form, profile picture uploader, or document manager, Django provides robust tools to handle file uploads securely and efficiently.
Overview
Django’s forms framework allows handling file uploads using:
-
FileField
orImageField
in forms or models -
request.FILES
for handling uploaded files -
MEDIA_ROOT
andMEDIA_URL
for file storage
Step-by-Step: Django File Uploading
Step 1: Configure Project Settings
Add the following to your settings.py
file:
# settings.py
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
And in development, serve uploaded files by updating urls.py
:
# project/urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... your app URLs here
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Step 2: Create a Model with FileField or ImageField
# models.py
from django.db import models
class Document(models.Model):
title = models.CharField(max_length=100)
uploaded_file = models.FileField(upload_to='documents/')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
You can also use ImageField
for image-specific uploads:
image = models.ImageField(upload_to='images/')
Note: For
ImageField
, install Pillow:
pip install Pillow
Step 3: Create a ModelForm for File Upload
# forms.py
from django import forms
from .models import Document
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ['title', 'uploaded_file']
Step 4: Create a View to Handle Uploads
# views.py
from django.shortcuts import render, redirect
from .forms import DocumentForm
def upload_file_view(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('upload_success')
else:
form = DocumentForm()
return render(request, 'upload.html', {'form': form})
Step 5: Create Upload Template
<!-- templates/upload.html -->
<h2>Upload a File</h2>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
⚠️ Always include
enctype="multipart/form-data"
in the form for file uploads to work.
Step 6: Add URLs
# urls.py
from django.urls import path
from .views import upload_file_view
urlpatterns = [
path('upload/', upload_file_view, name='file_upload'),
path('upload/success/', lambda r: render(r, 'upload_success.html'), name='upload_success'),
]
Where Are Files Stored?
-
Files are uploaded to
MEDIA_ROOT
/upload_to
. -
If
upload_to='documents/'
and the file isreport.pdf
, it goes to:
media/documents/report.pdf
You can access them in templates using:
<a href="{{ document.uploaded_file.url }}">{{ document.title }}</a>
Customize Upload Behavior
Dynamic Upload Paths
def user_directory_path(instance, filename):
return f'user_{instance.id}/{filename}'
class Profile(models.Model):
avatar = models.ImageField(upload_to=user_directory_path)
Validating File Types & Size
Limit File Size
# forms.py
def clean_uploaded_file(self):
file = self.cleaned_data['uploaded_file']
if file.size > 5*1024*1024: # 5MB
raise forms.ValidationError("File too large ( > 5MB )")
return file
Validate File Type
import os
def clean_uploaded_file(self):
file = self.cleaned_data['uploaded_file']
ext = os.path.splitext(file.name)[1]
valid_extensions = ['.pdf', '.docx']
if ext not in valid_extensions:
raise forms.ValidationError('Unsupported file extension.')
return file
Downloading Uploaded Files
You can link to uploaded files via:
<a href="{{ document.uploaded_file.url }}" download>Download</a>
Common Pitfalls
Problem | Cause | Fix |
---|---|---|
File not uploading | Missing enctype |
Add enctype="multipart/form-data" |
File not saved | Forgot request.FILES |
Pass request.FILES to the form |
Invalid image error | Pillow not installed | Run pip install Pillow |
404 for media files | Improper URL setup | Serve media in urls.py with static() |
✅ Tips
-
Use
ImageField
for images and validate dimensions if needed. -
Store files in subfolders using
upload_to
. -
Clean up old files using custom delete logic or third-party apps like
django-cleanup
. -
Serve media from a CDN or external storage like AWS S3 in production.
-
Add a progress bar using JavaScript/AJAX for better UX on large uploads.
Conclusion
Django makes file uploading easy and secure. With just a few configurations and the built-in FileField
, you can build upload features that are production-ready.
Whether you're dealing with documents, images, or media files, Django provides all the tools to manage file handling, validation, and access.