logo oujood
🔍

Upload de fichiers dans Django

Django gère nativement l'upload de fichiers et d'images. Ce chapitre couvre la configuration complète : paramètres MEDIA dans settings.py, champs FileField et ImageField, formulaire avec enctype multipart, traitement dans la vue et affichage dans les templates.

OUJOOD.COM

Configurer les fichiers médias dans settings.py

Django distingue les fichiers statiques (CSS, JS, images fixes) des fichiers médias (fichiers uploadés par les utilisateurs). Ces derniers sont stockés dans un dossier séparé et servis via une URL dédiée. Deux paramètres dans settings.py :

  📋 Copier le code

# settings.py
import os

# URL préfixe pour accéder aux fichiers médias
MEDIA_URL = '/media/'

# Dossier où Django stocke les fichiers uploadés
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Il faut aussi déclarer cette URL dans urls.py du projet pour que Django serve les médias en développement :

  📋 Copier le code

# monprojet/urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('membres/', include('membres.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Remarque : static() ne sert les médias que si DEBUG = True. En production, c'est le serveur web (Nginx, Apache) ou un service de stockage (AWS S3) qui prend en charge cette tâche.

Ajouter un champ de fichier au modèle

FileField stocke n'importe quel type de fichier. ImageField est une spécialisation qui vérifie que le fichier uploadé est bien une image (nécessite la bibliothèque Pillow).

  📋 Copier le code

from django.db import models

class Membres(models.Model):
    prenom = models.CharField(max_length=255)
    nom    = models.CharField(max_length=255)
    mail   = models.EmailField()
    # upload_to définit le sous-dossier dans MEDIA_ROOT
    avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
    cv     = models.FileField(upload_to='documents/cv/', blank=True, null=True)

Le paramètre upload_to peut être une chaîne fixe ou une fonction qui génère un chemin dynamique. Les fichiers seront stockés dans MEDIA_ROOT/avatars/ et MEDIA_ROOT/documents/cv/.

Installez Pillow si vous utilisez ImageField :

  📋 Copier le code

pip install Pillow

Après avoir modifié le modèle, lancez les migrations :

  📋 Copier le code

python manage.py makemigrations
python manage.py migrate

Créer le formulaire d'upload

Un ModelForm suffit — Django génère automatiquement un FileInput pour les champs fichiers :

  📋 Copier le code

from django import forms
from .models import Membres

class MembreForm(forms.ModelForm):
    class Meta:
        model  = Membres
        fields = ['prenom', 'nom', 'mail', 'avatar', 'cv']

Traiter l'upload dans la vue

La différence essentielle avec un formulaire texte : les fichiers uploadés arrivent dans request.FILES, pas dans request.POST. Il faut passer les deux au formulaire.

  📋 Copier le code

from django.shortcuts import render, redirect, get_object_or_404
from .forms import MembreForm

def ajouter_membre(request):
    if request.method == 'POST':
        # request.FILES est obligatoire pour les formulaires avec fichiers
        form = MembreForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = MembreForm()
    return render(request, 'ajout.html', {'form': form})

def modifier_membre(request, id):
    membre = get_object_or_404(Membres, id=id)
    if request.method == 'POST':
        form = MembreForm(request.POST, request.FILES, instance=membre)
        if form.is_valid():
            form.save()
            return redirect('index')
    else:
        form = MembreForm(instance=membre)
    return render(request, 'modifier.html', {'form': form})

Le template — enctype obligatoire

Un formulaire qui contient un champ fichier doit avoir l'attribut enctype="multipart/form-data" sur la balise <form>. Sans lui, le fichier ne sera jamais transmis au serveur.

  📋 Copier le code

<!DOCTYPE html>
<html>
<body>
<h1>Ajouter un membre</h1>

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Enregistrer</button>
</form>

</body>
</html>

Afficher un fichier uploadé dans le template

Django stocke le chemin du fichier en base de données. L'attribut .url génère l'URL complète à partir de MEDIA_URL :

  📋 Copier le code

{% if membre.avatar %}
    <img src="{{ membre.avatar.url }}" alt="Avatar de {{ membre.prenom }}">
{% else %}
    <p>Aucun avatar.</p>
{% endif %}

{% if membre.cv %}
    <a href="{{ membre.cv.url }}">Télécharger le CV</a>
{% endif %}

Testez toujours {% if membre.avatar %} avant d'utiliser .url — si le champ est vide, appeler .url lève une exception.

Par carabde | Mis à jour le 06 mai 2026