Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🐍 Django – Installation & Déploiement complet

Guide complet IDEO‑Lab pour partir de zéro et aller jusqu'au déploiement Nginx/Gunicorn/WAMP.

1.1

Vue d'ensemble Django

Django, MTV, sécurité intégrée, admin auto.

MTV Sécu ORM
1.2

Installation (Linux/Win)

Python, venv, pip, installation Django.

venv pip Win/Linux
1.3

Créer le projet

startproject, startapp, arborescence.

startproject apps
1.4

Paramétrer settings.py

DEBUG, ALLOWED_HOSTS, apps, templates.

settings.py ALLOWED_HOSTS

1.4B Générateur settings.py

Outil interactif : Créez votre configuration Django idéale en quelques clics.

Interactif Generator
2.1

Apps de base Django

accounts, blog, core, dashboard.

accounts admin reusable
2.2

Routage & URLs

urls.py projet + urls.py app.

path include

2.4 Health Check & Analyzer

Outil expérimental : Cross-reference URLs/Templates pour détecter les "NoReverseMatch" avant le crash.

Analysis Anti-Crash
2.3

Templates & static

Organisation /templates et /static.

extends static base.html
3.1

Modèles & ORM

models.Model, migrations, requêtes ORM.

models migrate queryset
3.2

Connexion BDD

SQLite, PostgreSQL, MariaDB.

sqlite pgsql mariadb
3.3

Admin Django

Activation et customisation rapide.

admin ModelAdmin
4.1

Formulaires

Django forms, ModelForm, validation.

forms ModelForm
4.2

Auth & Users

Login, logout, permissions.

login permission
4.3

API (DRF option)

Base DRF, serializers, viewsets.

DRF API
5.1

Runserver & gestion

python manage.py runserver.

runserver manage.py
5.2

Gunicorn (Linux)

Serveur WSGI pour la prod.

gunicorn systemd
5.3

Nginx reverse proxy

Proxy, static, media, SSL.

nginx proxy_pass
5.4

WAMP / Windows

Django sous Windows, Apache.

wamp mod_wsgi
6.1

Sécurité & .env

DEBUG, secrets, CSRF.

.env secrets
6.2

Optimisation

Collectstatic, cache, logs.

collectstatic logs
6.3

Déploiement complet

Arbo serveur, services, backups.

deploy prod
7.1

Cheat‑sheet Django

Commandes fréquentes.

cheat cmd
1.1 Vue d'ensemble Django & Architecture
Django en bref

Django est un framework web Python de haut niveau, conçu pour les développeurs perfectionnistes ayant des délais serrés. Il suit le principe DRY (Don't Repeat Yourself) et privilégie la configuration explicite.

  • Date de création : 2005 (Lawrence Journal-World).
  • Langage : Python (3.10+ recommandé pour Django 5).
  • Type : Monolithique (tout inclus), mais modulaire via les "Apps".
Architecture MTV vs MVC

Django utilise une variation du MVC appelée MTV.

                            MVC Classique      |      Django MTV
                            ------------------------------------------
                            Model (Données)      |  Model (models.py)
                            View (Affichage)     |  Template (html)
                            Controller (Logique) |  View (views.py)
                        

Note: Le "Controller" est en réalité géré par le framework lui-même (URL Dispatching).


Diagramme de flux MTV
                    Navigateur (Client)
                    │
                    ▼ (Requête HTTP)
                    [ URL Dispatcher (urls.py) ] ──▶  Choisit la bonne vue
                    │
                    ▼
                    [ View (views.py) ] ◀──┐
                    │  │               │ (ORM: Python <-> SQL)
                    │  │ logique       ▼
                    │  └────────── [ Model (models.py) ] ◄───► [ Base de Données ]
                    │
                    ▼ (Context Data)
                    [ Template (HTML) ] ──▶ Génère la page finale
                    │
                    ▼
                    Réponse HTTP (HTML, JSON, File...)
                
Le chemin d'une requête

Comprendre le cycle de vie est crucial pour le débogage et la performance.

  1. WSGI/ASGI : Le serveur web (Nginx/Gunicorn) passe la main à Django.
  2. Middleware (Entrée) : La requête traverse les couches de sécurité, session, CSRF.
  3. URL Resolution : Django cherche une correspondance dans urlpatterns.
  4. View Processing : La fonction ou classe est exécutée.
  5. Middleware (Sortie) : La réponse traverse les couches en sens inverse.
Le concept d'"Oignon" (Middleware)
                            Requête Entrante ⬇️      ⬆️ Réponse Sortante
                            ┌──────────────────────────────────────────┐
                            │ SecurityMiddleware                       │
                            │  ┌────────────────────────────────────┐  │
                            │  │ SessionMiddleware                  │  │
                            │  │  ┌──────────────────────────────┐  │  │
                            │  │  │ CommonMiddleware             │  │  │
                            │  │  │  ┌────────────────────────┐  │  │  │
                            │  │  │  │ CSRFViewMiddleware     │  │  │  │
                            │  │  │  │  ┌──────────────────┐  │  │  │  │
                            │  │  │  │  │ AuthMiddleware   │  │  │  │  │
                            │  │  │  │  │    YOUR VIEW     │  │  │  │  │
                            │  │  │  │  └──────────────────┘  │  │  │  │
                            │  │  │  └────────────────────────┘  │  │  │
                            │  │  └──────────────────────────────┘  │  │
                            │  └────────────────────────────────────┘  │
                            └──────────────────────────────────────────┘
                        
Pourquoi dit-on "Batteries Included" ?

Contrairement aux micro-frameworks (Flask, FastAPI), Django fournit nativement les outils pour 90% des besoins web standards.

ORM Un Object-Relational Mapper puissant qui supporte PostgreSQL, MySQL, SQLite et Oracle sans changer une ligne de code.
Admin Une interface d'administration (CRUD) générée automatiquement à partir de vos modèles. Prête pour la prod.
Auth Système complet : Utilisateurs, Groupes, Permissions, Cookies, Sessions, Hashing de mots de passe (PBKDF2).
Sécurité par défaut

Django protège proactivement contre :

  • SQL Injection : Via l'utilisation des querysets paramétrés de l'ORM.
  • XSS (Cross Site Scripting) : Les templates échappent automatiquement les variables dangereuses.
  • CSRF (Cross Site Request Forgery) : Tokens obligatoires pour les formulaires POST.
  • Clickjacking : Protection via headers X-Frame-Options.
Arborescence Typique
                            my_project/             # Racine (Repo Git)
                            │
                            ├── manage.py           # CLI (Command Line Interface)
                            ├── requirements.txt    # Dépendances
                            ├── .env                # Secrets (ne pas commiter)
                            │
                            ├── my_project/         # Dossier de configuration
                            │   ├── __init__.py
                            │   ├── settings.py     # Config globale
                            │   ├── urls.py         # Routes principales
                            │   ├── wsgi.py         # Point d'entrée serveur Sync
                            │   └── asgi.py         # Point d'entrée serveur Async
                            │
                            └── core/               # Une "App" (Module métier)
                            ├── migrations/     # Versionning BDD
                            ├── admin.py        # Config Admin
                            ├── apps.py         # Config App
                            ├── models.py       # Structure des données
                            ├── tests.py        # Tests unitaires
                            ├── urls.py         # Routes de l'app
                            └── views.py        # Logique des vues
                        
Commandes Essentielles

Le fichier manage.py est votre baguette magique.

CommandeDescription
runserverLance le serveur de dev (hot-reload).
makemigrationsDétecte les changements dans models.py.
migrateApplique les changements SQL en base.
createsuperuserCrée un admin avec accès complet.
shellOuvre un shell Python avec le contexte Django chargé.
0.x Vue d'ensemble des briques majeures de Django
Architecture conceptuelle d’un projet Django

Vue “macro” d’un projet : du noyau framework jusqu’aux briques métier. Idéal pour expliquer Django en 1 slide.

                    Django Project
                    ├── Core & Settings
                    │   ├── settings.py (config, I18N, DB, sécurité)
                    │   ├── urls.py (routing)
                    │   └── wsgi/asgi.py (interface serveur)
                    │
                    ├── Apps (briques métiers réutilisables)
                    │   ├── models.py        <= ORM (schéma & logique de données)
                    │   ├── views.py         <= logique métier / contrôleur
                    │   ├── templates/       <= rendu HTML / UI
                    │   ├── forms.py         <= validation & UX des formulaires
                    │   └── admin.py         <= back-office d’administration
                    │
                    ├── Cross-Cutting Concerns
                    │   ├── Middleware       (logs, sécurité, perf, monitoring)
                    │   ├── Auth / Permissions
                    │   ├── Messages / Sessions
                    │   └── Cache / Files / Storage
                    │
                    └── Intégrations externes
                    ├── Base de données (PostgreSQL, MariaDB…)
                    ├── Cache (Redis, Memcached)
                    ├── File storage (S3, GCS, disque…)
                    ├── Tâches asynchrones (Celery, RQ…)
                    └── APIs / Services tiers (REST, GraphQL, webhooks…)
                
Usage : ce schéma peut servir de “carte mentale” en début de formation Django, avant d’entrer dans chaque chapitre (URLs, ORM, templates, etc.).
Tableau des briques majeures de Django

Les 11 piliers “structurants” du framework, avec leur rôle et quelques mots-clés clés.

#PilierRôle principalMots-clés / Fichiers
1Core & SettingsConfiguration globale du projet et enregistrement des apps.settings.py, INSTALLED_APPS, MIDDLEWARE, apps.py
2Routing (URLs)Fait le lien entre une URL et une vue Python.urls.py, path(), re_path(), namespaces
3Views & HTTPLogique métier, orchestration des réponses HTTP.FBV/CBV, HttpRequest, HttpResponse, mixins
4TemplatesRendu HTML (ou texte) côté serveur, avec tags & filtres.{% extends %}, {% include %}, filters, context processors
5ORM & ModelsAbstraction SQL, mapping objet <-> base de données.models.py, QuerySet, managers, migrations
6Forms & ValidationValidation déclarative des données et génération de formulaires.forms.Form, ModelForm, clean(), widgets
7SécuritéProtection CSRF/XSS, gestion des cookies, headers de sécurité.CSRF, clickjacking, host validation, password hashing
8Auth & PermissionsGestion des utilisateurs, groupes, droits d’accès.User, Group, permissions, auth backends, decorators
9AdminBack-office auto-généré pour gérer les modèles.admin.site.register, ModelAdmin, inlines, filters
10Static, Media & StorageGestion des assets (CSS/JS/images) et des fichiers uploadés.STATIC_URL, STATIC_ROOT, MEDIA_ROOT, storage backends
11I18N, Timezones & LocalisationMulti-langues et gestion des fuseaux horaires.LANGUAGE_CODE, USE_I18N, USE_TZ, ugettext
Astuce pédagogique : tu peux utiliser ce tableau comme “table des matières” pour la section Django de ideo-lab, chaque ligne pointant vers une autre modal détaillée.
Écosystème Django & briques complémentaires

Django fournit un noyau complet, mais la plupart des projets modernes ajoutent des “super-pouvoirs” via quelques librairies phares.

API & sérialisation
AddonUsage principal
Django REST FrameworkConstruire des APIs REST robustes (sérialisation, viewsets, permissions).
Graphene-DjangoSchema GraphQL au-dessus de l’ORM Django.
Tâches asynchrones & temps différé
CeleryExécution de tâches en arrière-plan (emails, batchs lourds, ETL).
Redis / RabbitMQBroker & backend de résultats pour Celery.
Authentification avancée & Social Login
django-allauthGestion complète de l’inscription, login, social auth (Google, GitHub…).
Debug, perf & tooling
Django Debug ToolbarProfiling des requêtes SQL, temps de rendu, contexte templates.
SentryMonitoring des erreurs et traces en production.
django-extensionsShell plus riche, diagrammes de modèles, commandes de management.
Idée ideo-lab : chaque addon peut avoir sa propre mini-modal “Django + Celery”, “Django + DRF”, etc., avec un diagramme comme ceux que tu as déjà générés (ORM, Celery…).
1.2 Installation & Environnement Virtuel
Vérification de Python

Django est un framework Python. La version requise dépend de la version de Django visée.

  • Django 5.x : Python 3.10, 3.11, 3.12+
  • Django 4.2 (LTS) : Python 3.8 à 3.12
                            # Vérifier la version
                            python --version
                            # ou sous Linux/Mac
                            python3 --version
                        
Installation Système

Avant de créer un environnement virtuel, assurez-vous d'avoir Python et pip installés globalement.

Ubuntu / Debian
sudo apt update
                            sudo apt install python3 python3-venv python3-pip -y
Windows

Téléchargez l'installateur sur python.org.
IMPORTANT : Cochez la case Add Python to PATH lors de l'installation.

Pourquoi un environnement virtuel (venv) ?

Le venv est un dossier isolé contenant son propre exécutable Python et ses propres librairies. Il permet d'avoir Django 4 sur le projet A et Django 5 sur le projet B sans conflit.


1. Création

Placez-vous dans le dossier de votre projet.

                            # Créer le dossier "venv"
                            python -m venv venv
                            # ou
                            python3 -m venv venv
                        
2. Activation

Une fois activé, votre prompt terminal changera (ex: (venv) user@pc...).

OSCommande
Linux / Macsource venv/bin/activate
Windows (CMD)venv\Scripts\activate.bat
Windows (PowerShell)venv\Scripts\Activate.ps1
Assurez-vous que votre venv est activé avant de lancer ces commandes.
Installation Standard
                            # Mettre à jour pip (bon réflexe)
                            python -m pip install --upgrade pip

                            # Installer la dernière version stable
                            pip install django

                            # Vérifier l'installation
                            python -m django --version
                        
Version Spécifique & Requirements
                            # Installer une version précise (ex: LTS)
                            pip install django==4.2.7

                            # Figer les versions pour la prod
                            pip freeze > requirements.txt

                            # Installer depuis un fichier
                            pip install -r requirements.txt
                        
Structure recommandée
                    mon_projet/
                    ├── venv/                # L'environnement (NE PAS TOUCHER)
                    ├── .gitignore           # Ignorer venv/, .env, *.pyc
                    ├── requirements.txt     # Liste des paquets
                    └── src/                 # Le code source (optionnel, pour séparer)
                
Erreur : "Scripts is disabled on this system" (Windows)

PowerShell bloque l'exécution de scripts par défaut.

                            # Solution : Autoriser l'exécution (Admin)
                            Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
                        
Erreur : "pip command not found"

Python n'est pas dans le PATH ou pip n'est pas installé.

                            # Essayez d'utiliser le module python directement
                            python -m pip install django
                            # Au lieu de juste "pip install ..."
                        

Bonnes Pratiques
  • DO : Toujours utiliser un venv par projet.
  • DO : Ajouter venv/ à votre fichier .gitignore immédiatement.
  • DON'T : Ne jamais renommer ou déplacer le dossier venv une fois créé (cela casse les chemins absolus internes). Supprimez-le et recréez-le si besoin.
1.3 Architecture Projet, Création d'Apps & Anatomie
La distinction Projet vs Application

C'est la confusion n°1 des débutants. Django est conçu pour la **réutilisabilité**. Une application ne devrait pas "savoir" à quel projet elle appartient.

PROJET (Le Conteneur)

C'est votre site web spécifique (ex: mon_e_commerce). Il contient la configuration (BDD, langue, timezones) et le routage global.

APP (Le Module)

C'est une fonctionnalité autonome (ex: forum, blog, auth). Une app bien écrite peut être copiée/collée dans un autre projet et fonctionner immédiatement.

Architecture Multi-Apps (Pattern Standard)
                            ┌───────────────── PROJET: "IDEO_PLATFORM" ─────────────────┐
                            │ settings.py (Connecteur DB: PostgreSQL)                   │
                            │ urls.py (Dispatcher global)                               │
                            │                                                           │
                            │ ┌──────────────┐   ┌──────────────┐   ┌───────────────┐   │
                            │ │ APP "Core"   │   │ APP "Blog"   │   │ APP "Users"   │   │
                            │ │ - Homepage   │   │ - Articles   │   │ - Login       │   │
                            │ │ - Base Tpl   │   │ - Comments   │   │ - Register    │   │
                            │ │ - Utils      │   │ - Tags       │   │ - Profile     │   │
                            │ └──────┬───────┘   └──────┬───────┘   └──────┬────────┘   │
                            │        │                  │                  │            │
                            └────────┼──────────────────┼──────────────────┼────────────┘
                            │                  │                  │
                            ▼                  ▼                  ▼
                            ┌───────────────────────────────────────────────────┐
                            │           ORM (Couche d'abstraction)              │
                            └───────────────────────────────────────────────────┘
                            ▼                  ▼                  ▼
                            [Table: core_*]    [Table: blog_*]    [Table: users_*]
                        

Chaque app gère ses propres tables en BDD, préfixées par le nom de l'app.

1. Création du Projet (La bonne méthode)

L'erreur classique est de créer des dossiers imbriqués inutiles.

                            # ❌ Mauvaise pratique (crée projet/projet/manage.py)
                            django-admin startproject mysite

                            # ✅ Bonne pratique (le point final est crucial)
                            mkdir ideolab_project
                            cd ideolab_project
                            django-admin startproject config . 
                        

Pourquoi appeler le dossier de config config au lieu du nom du projet ?

  • C'est une convention moderne.
  • Ça distingue clairement la configuration des applications métier.
  • Ça simplifie les imports (ex: from config import settings).
2. Création des Apps
                            python manage.py startapp core
                            python manage.py startapp accounts
                            python manage.py startapp dashboard
                        
3. Le Registre des Apps (INSTALLED_APPS)

Si une app n'est pas ici, Django l'ignore (pas de migrations, pas de templates, pas de tests).

                            # config/settings.py

                            INSTALLED_APPS = [
                            # Apps natives Django (Batteries)
                            'django.contrib.admin',
                            'django.contrib.auth',
                            'django.contrib.contenttypes',
                            'django.contrib.sessions',
                            'django.contrib.messages',
                            'django.contrib.staticfiles',

                            # Apps Tiers (Libs installées via pip)
                            'rest_framework',
                            'debug_toolbar',

                            # Vos Apps Locales (Ordre important pour l'override)
                            'core.apps.CoreConfig',      # Recommandé: utiliser la config class
                            'accounts.apps.AccountsConfig',
                            'dashboard.apps.DashboardConfig',
                            ]
                        
Anatomie détaillée d'un projet Django 5.x

Chaque fichier a un rôle précis dans le cycle de vie.

📁 Niveau Racine (Root)
FichierFonction
manage.pyWrapper autour de django-admin. Utilise les settings du projet. Ne jamais modifier.
db.sqlite3BDD fichier par défaut. À exclure du Git.
requirements.txtListe des dépendances pip (pour le déploiement).
.envVariables d'environnement (Secret key, DB password).
📁 Dossier de Config (config/)
FichierFonction
settings.pyLe cerveau. Tout se décide ici (Middleware, Apps, DB).
urls.pyLa table des matières. Aiguille les requêtes vers les Apps.
wsgi.py(Web Server Gateway Interface). Point d'entrée pour Apache/Gunicorn (Synchrone).
asgi.py(Asynchronous SGI). Point d'entrée pour Daphne/Uvicorn (Websockets, Async).
📁 Dossier App (ex: core/)
                            core/
                            ├── migrations/      # Historique SQL (Versionning de la BDD)
                            │   └── 0001_initial.py
                            ├── __init__.py      # Fait du dossier un package Python
                            ├── admin.py         # Configuration de l'interface /admin/
                            ├── apps.py          # Métadonnées (Nom verbose, Signaux au démarrage)
                            ├── models.py        # ORM: Définition des tables et relations
                            ├── tests.py         # Tests unitaires (unittest/pytest)
                            ├── views.py         # Logique métier (Request -> Response)
                            ├── urls.py          # (Optionnel mais recommandé) Routes locales
                            ├── forms.py         # (À créer) Gestion des formulaires & validation
                            ├── signals.py       # (À créer) Hooks événementiels
                            └── management/      # (À créer) Commandes custom manage.py
                            └── commands/
                        
Le Flux de contrôle (Dispatcher)

Comment une URL devient une page HTML ? Mécanisme de délégation.

1. URL Globale (config/urls.py)

On "monte" les apps sur des préfixes.

                            from django.urls import path, include

                            urlpatterns = [
                            path('admin/', admin.site.urls),

                            # Délégation: Tout ce qui commence par "blog/" 
                            # est envoyé à l'app blog.
                            path('blog/', include('blog.urls')), 

                            # Délégation: La racine est gérée par core
                            path('', include('core.urls')), 
                            ]
                        
2. URL Locale (blog/urls.py)

On définit les routes finales et les variables.

                            from django.urls import path
                            from . import views

                            # app_name permet le reverse routing :  {% url 'blog:detail' %}   
                            app_name = 'blog' 

                            urlpatterns = [
                            # Match: /blog/
                            path('', views.post_list, name='list'),

                            # Match: /blog/42/ (Path converters)
                            path('<int:id>/', views.post_detail, name='detail'),

                            # Match: /blog/slug-titre/
                            path('<slug:slug>/', views.post_by_slug, name='slug_detail'),
                            ]
                        

3. La Vue (Function Based View vs Class Based View)
Function Based View (FBV)

Simple, explicite, idéal pour débuter ou pour de la logique complexe spécifique.

                            from django.shortcuts import render, get_object_or_404
                            from .models import Post

                            def post_detail(request, id):
                            # Logique métier
                            post = get_object_or_404(Post, pk=id)
                            context = {'post': post}
                            return render(request, 'blog/detail.html', context)
                        
Class Based View (CBV)

Puissant, concis, orienté objet. Idéal pour les CRUD standards.

                            from django.views.generic import DetailView
                            from .models import Post

                            class PostDetailView(DetailView):
                            model = Post
                            template_name = 'blog/detail.html'
                            context_object_name = 'post'
                            # Gère automatiquement le 404 et la requête
                        
Préparer la production dès le jour 1
1. Séparer les Settings

Au lieu d'un seul settings.py, créez un package.

                            config/
                            └── settings/
                            ├── __init__.py
                            ├── base.py   # Config commune (Apps, Auth...)
                            ├── dev.py    # Debug=True, Console Email
                            └── prod.py   # Debug=False, S3, Sentry
                        

Lancer avec : python manage.py runserver --settings=config.settings.dev

2. Le fichier .gitignore (Vital)

Ne committez jamais ces fichiers :

                            # Python
                            __pycache__/
                            *.py[cod]
                            venv/
                            env/

                            # Django
                            *.log
                            local_settings.py
                            db.sqlite3
                            media/

                            # Environment variables
                            .env
                        

3. Organisation des Templates et Static

Bien que Django permette de mettre les templates dans chaque app, il est souvent plus propre d'avoir un dossier global à la racine pour surcharger facilement.

                    # settings.py
                    TEMPLATES = [{
                    'DIRS': [BASE_DIR / 'templates'], # Dossier global
                    'APP_DIRS': True, # Cherche aussi dans app/templates/
                    # ...
                    }]

                    # Structure
                    templates/
                    ├── base.html       # Squelette global
                    ├── components/     # Navbar, Footer
                    ├── blog/           # Surcharge app blog
                    └── accounts/       # Surcharge app accounts
                
1.4 Paramétrage Avancé de settings.py & Gestion d'Environnement
Les Fondamentaux

Ces variables définissent l'identité et la sécurité du projet.

BASE_DIR
                            from pathlib import Path
                            # Pointe vers la racine du projet (là où est manage.py)
                            BASE_DIR = Path(__file__).resolve().parent.parent
                        
SECRET_KEY
                            # CRITIQUE : Utilisé pour signer les cookies, sessions, CSRF.
                            # Ne JAMAIS commiter la vraie clé.
                            SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
                        
DEBUG

Le paramètre le plus dangereux.

  • True (Dev) : Affiche des pages d'erreur détaillées (avec extraits de code, variables, SQL).
  • False (Prod) : Affiche "Server Error (500)". Obligatoire en production.
ALLOWED_HOSTS

Liste blanche des domaines/IPs autorisés à servir le site (Protection Host Header Injection).

                            if DEBUG:
                            ALLOWED_HOSTS = [] # Autorise localhost, 127.0.0.1, [::1]
                            else:
                            ALLOWED_HOSTS = ['ideo-lab.com', 'www.ideo-lab.com', '192.168.1.50']
                        
Gestion des Fichiers (Static & Media)

Comprendre la différence entre static (code) et media (uploads utilisateur) est vital.

Fichiers Statiques (CSS, JS, IMG du thème)
                            # URL publique (ex: /static/css/style.css)
                            STATIC_URL = 'static/'

                            # Où Django cherche les fichiers en DEV
                            STATICFILES_DIRS = [
                            BASE_DIR / 'static', 
                            ]

                            # Où Django RASSEMBLE les fichiers en PROD
                            # (via la commande "collectstatic")
                            STATIC_ROOT = BASE_DIR / 'staticfiles'
                        
Fichiers Media (Uploads Users)
                            # URL publique (ex: /media/avatars/user1.jpg)
                            MEDIA_URL = 'media/'

                            # Dossier physique de stockage
                            MEDIA_ROOT = BASE_DIR / 'media'
                        

Note: En production, Nginx servira directement STATIC_ROOT et MEDIA_ROOT.


Templates
                    TEMPLATES = [
                    {
                    'BACKEND': 'django.template.backends.django.DjangoTemplates',
                    'DIRS': [BASE_DIR / 'templates'], # Pour utiliser un dossier global
                    'APP_DIRS': True,                 # Cherche aussi dans app/templates/
                    'OPTIONS': {
                    'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request', # Requis par Allauth/Admin
                    'django.contrib.auth.context_processors.auth', # Ajoute "user" dans les tpl
                    'django.contrib.messages.context_processors.messages',
                    ],
                    },
                    },
                    ]
                
Base de Données (DATABASES)

Django supporte officiellement PostgreSQL, MariaDB, MySQL, Oracle et SQLite.

Option A: SQLite (Dev)
                            DATABASES = {
                            'default': {
                            'ENGINE': 'django.db.backends.sqlite3',
                            'NAME': BASE_DIR / 'db.sqlite3',
                            }
                            }
                        
Option B: PostgreSQL (Prod/Recommandé)
                            DATABASES = {
                            'default': {
                            'ENGINE': 'django.db.backends.postgresql',
                            'NAME': 'ideo_db',
                            'USER': 'ideo_user',
                            'PASSWORD': os.environ.get('DB_PASS'),
                            'HOST': 'localhost',
                            'PORT': '5432',
                            }
                            }
                        
Internationalisation (I18N)
                            # Code langue par défaut (français)
                            LANGUAGE_CODE = 'fr-fr'

                            # Fuseau horaire (Stockage UTC en base, affichage local)
                            TIME_ZONE = 'Europe/Paris'

                            # Activer la traduction
                            USE_I18N = True

                            # Activer le support des timezones (Recommandé: True)
                            USE_TZ = True
                        

Si USE_TZ = True, Django stocke tout en UTC. La conversion vers 'Europe/Paris' se fait uniquement à l'affichage dans le template.

Professionnaliser la gestion des settings

Ne modifiez plus settings.py à la main pour passer de Dev à Prod. Utilisez ces outils.

1. python-dotenv (Le Standard Simple)

Charge les variables d'un fichier .env dans os.environ.

                            # Installation
                            pip install python-dotenv

                            # Dans manage.py et wsgi.py (au tout début)
                            from dotenv import load_dotenv
                            load_dotenv() # Cherche .env à la racine

                            # Dans settings.py
                            import os
                            SECRET_KEY = os.getenv('SECRET_KEY')
                        
2. django-environ (Le "Douze Factor App")

Plus puissant : gère le typage (bool, int, list) et les schémas de BDD (DATABASE_URL).

                            # Installation
                            pip install django-environ

                            # Dans settings.py
                            import environ
                            env = environ.Env(
                            # Valeurs par défaut
                            DEBUG=(bool, False)
                            )
                            environ.Env.read_env(BASE_DIR / '.env')

                            DEBUG = env('DEBUG') # Convertit auto "True" en bool
                            # Parse l'URL postgres://user:pass@host:port/db
                            DATABASES = {'default': env.db()} 
                        
Exemple de fichier .env (à ne pas commiter !)
                    DEBUG=True
                    SECRET_KEY=votre-super-cle-secrete-inviolable
                    DATABASE_URL=postgres://ideo:password@localhost:5432/ideo_db
                    ALLOWED_HOSTS=127.0.0.1,localhost
                
Architecture "Split Settings"

Pour les gros projets, un seul fichier settings.py devient illisible. Voici comment le diviser.

                    my_project/
                    └── settings/
                    ├── __init__.py   # Vide (ou logique de sélection)
                    ├── base.py       # (Base) Apps, Auth, I18N, Templates
                    ├── dev.py        # (Dev) Debug=True, SQLite, Debug Toolbar, Console Email
                    ├── prod.py       # (Prod) Debug=False, PostgreSQL, S3, Sentry, Redis
                    └── test.py       # (Test) Settings optimisés pour la rapidité des tests
                
Comment lier les fichiers ?

Dans dev.py et prod.py, on importe tout depuis base.

                            # settings/dev.py
                            from .base import *

                            DEBUG = True
                            ALLOWED_HOSTS = ['localhost']

                            # Outils de dev uniquement
                            INSTALLED_APPS += ['debug_toolbar']
                            MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
                        
Comment lancer Django ?

Il faut spécifier quel fichier de settings utiliser.

                            # En développement
                            python manage.py runserver --settings=my_project.settings.dev

                            # En production (Gunicorn/WSGI)
                            export DJANGO_SETTINGS_MODULE=my_project.settings.prod
                            gunicorn my_project.wsgi:application
                        
Astuce : L'addon django-split-settings permet de faire des inclusions encore plus propres (via glob patterns), mais l'héritage Python simple ci-dessus couvre 95% des besoins.
Générateur settings.py (Version Pro)
1. Identité du Projet
2. Architecture & Auth
3. E-mails
2.1 Architecture Modulaire : Les Apps Fondamentales
Pourquoi découper en Apps ?

Dans un projet Django "Pro", on ne met pas tout dans une seule app. On sépare les responsabilités pour faciliter la maintenance, les tests et le travail en équipe.

Le "Standard IDEO-Lab" repose sur 4 piliers :

  • Core : Ce qui est partagé (Templates de base, Modèles abstraits, Mixins).
  • Accounts : Gestion des utilisateurs (Custom User, Auth, Profils).
  • Dashboard : L'espace privé post-login (Stats, CRUD métier).
  • Tools : Scripts, tâches de fond, analyseurs.
Diagramme de Dépendance
                            ┌──────────────────┐
                            │   Projet (Root)  │
                            └────────┬─────────┘
                            │
                            ┌─────▼──────┐
                            │ APP "Core" │ (Base Templates, Utils)
                            └─────┬──────┘
                            │ ▲
                            ┌─────────┤ │ (Hérite de Core)
                            │         ▼ │
                            ┌─────▼────┐  ┌───┴────────┐
                            │ Accounts │  │ Dashboard  │ ◀── (Dépend de Accounts)
                            └──────────┘  └────────────┘
                            ▲             │
                            └─────────────┘
                        
App "Core" : Les fondations invisibles

Cette app ne contient souvent pas d'URLs, mais fournit des outils pour les autres apps.

1. Modèles Abstraits (DRY)

Ne répétez jamais created_at et updated_at dans chaque modèle. Créez un modèle parent.

                            # core/models.py
                            from django.db import models

                            class TimeStampedModel(models.Model):
                            """
                            Classe de base abstraite qui ajoute
                            automatiquement les champs de date.
                            """
                            created_at = models.DateTimeField(auto_now_add=True)
                            updated_at = models.DateTimeField(auto_now=True)
                            is_active = models.BooleanField(default=True)

                            class Meta:
                            abstract = True # Django ne créera pas de table pour ceci
                        
2. Mixins de Vues

Ajoutez des fonctionnalités communes à vos Vues.

                            # core/mixins.py
                            from django.contrib.auth.mixins import UserPassesTestMixin

                            class SuperUserRequiredMixin(UserPassesTestMixin):
                            def test_func(self):
                            return self.request.user.is_superuser
                        
3. Templates Globaux

Structure recommandée :

                            templates/
                            ├── base.html           # Squelette (Header/Footer)
                            ├── partials/           # Fragments (Navbar, Sidebar)
                            │   ├── navbar.html
                            │   └── sidebar.html
                            └── core/               # Pages génériques
                            ├── home.html
                            └── 404.html
                        
App "Accounts" : Gestion de l'identité

C'est la première app à coder. Elle remplace le User par défaut de Django.

1. Custom User Model (OBLIGATOIRE)

Toujours faire ça avant la première migration !

                            # accounts/models.py
                            from django.contrib.auth.models import AbstractUser
                            from django.db import models

                            class User(AbstractUser):
                            # On ajoute nos champs spécifiques
                            avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
                            bio = models.TextField(max_length=500, blank=True)
                            is_verified = models.BooleanField(default=False)

                            def __str__(self):
                            return self.username
                        

N'oubliez pas AUTH_USER_MODEL = 'accounts.User' dans settings.py.

2. Vues d'Authentification
                            # accounts/urls.py
                            from django.urls import path
                            from django.contrib.auth import views as auth_views
                            from . import views

                            urlpatterns = [
                            path('login/', auth_views.LoginView.as_view(
                            template_name='accounts/login.html'
                            ), name='login'),

                            path('logout/', auth_views.LogoutView.as_view(), name='logout'),

                            path('register/', views.SignUpView.as_view(), name='register'),
                            ]
                        
App "Dashboard" : Le cœur de l'application

C'est ici que les utilisateurs connectés atterrissent. C'est le "Back-office client".

1. La Vue Principale (Protégée)
                            # dashboard/views.py
                            from django.contrib.auth.decorators import login_required
                            from django.shortcuts import render
                            from core.models import Metric # Exemple

                            @login_required # Sécurité basique
                            def dashboard_home(request):
                            context = {
                            'user_count': 150,
                            'recent_activities': [],
                            'page_title': 'Tableau de bord'
                            }
                            return render(request, 'dashboard/home.html', context)
                        
2. Structure des Templates

Le dashboard a souvent un layout différent du site public (Sidebar vs Topbar).

                            templates/dashboard/
                            ├── base_dashboard.html  # Étend base.html mais ajoute la Sidebar
                            ├── home.html            # Contenu spécifique
                            └── profile/
                            └── edit.html
                        
3. Exemple de template
                            {% extends "dashboard/base_dashboard.html" %}

                            {% block content %}
                            
Bienvenue
{% endblock %}
App "Tools" : L'atelier technique

Une app pour ranger vos scripts, commandes de gestion et utilitaires système.

1. Commandes de Gestion (Management Commands)

Permet de lancer des tâches via python manage.py ...

                            # tools/management/commands/cleanup_logs.py
                            from django.core.management.base import BaseCommand

                            class Command(BaseCommand):
                            help = 'Nettoie les vieux logs'

                            def handle(self, *args, **kwargs):
                            # Logique de nettoyage
                            self.stdout.write(self.style.SUCCESS('Logs nettoyés !'))
                        

Usage : python manage.py cleanup_logs

2. Template Tags personnalisés

Ajoutez des fonctions utilisables dans les templates HTML.

                            # tools/templatetags/ideo_extras.py
                            from django import template
                            import datetime

                            register = template.Library()

                            @register.filter(name='days_until')
                            def days_until(date):
                            delta = date - datetime.date.today()
                            return delta.days
                        

Usage HTML : {{ project.deadline|days_until }} jours restants

2.2 Le Système de Routage Avancé (URL Dispatcher)
Comment Django traite une URL ?

Quand une requête arrive (ex: /blog/2024/django-tuto/), Django suit ce processus :

  1. Il charge le module défini dans ROOT_URLCONF (généralement config/urls.py).
  2. Il parcourt la liste urlpatterns **dans l'ordre**, du haut vers le bas.
  3. Il s'arrête à la **première correspondance**.
  4. Si ça matche un include(), il coupe la partie matchée et envoie le reste à l'URLconf de l'app.
Diagramme de Délégation
                            URL Demandée:  /blog/articles/42/

                            [ROOT_URLCONF] (config/urls.py)
                            │
                            ├── path('admin/', ...)  ❌ (Pas de match)
                            │
                            ├── path('blog/', include('blog.urls')) ✅ MATCH !
                            │    │
                            │    └─ Django coupe "/blog/" et envoie "articles/42/"
                            │       à blog.urls
                            │
                            ▼
                            [APP_URLCONF] (blog/urls.py)
                            │
                            ├── path('', ...) ❌ (Attendait vide, reçu "articles/42/")
                            │
                            ├── path('articles//', views.detail) ✅ MATCH !
                            │
                            └─ Exécute: views.detail(request, pk=42)
                        
Capturer des arguments typés

Fini les Regex illisibles. Utilisez les "Path Converters" pour capturer et typer les variables d'URL.

ConverterType PythonExemple URLMatch
<int:id>int/user/42/
<str:name>str/user/john/✅ (Sauf le séparateur /)
<slug:slug>str/post/mon-super-titre/✅ (Lettres, chiffres, tirets)
<uuid:uid>UUID/detail/a0eebc99-9c0b.../✅ (Format UUID strict)
<path:file>str/files/dossier/img.jpg✅ (Inclut le séparateur /)
Exemple Standard
                            # urls.py
                            path('user/<str:username>/', views.profile),
                            path('archive/<int:year>/<int:month>/', views.archive),

                            # views.py
                            def profile(request, username): # username est un str
                            ...
                            def archive(request, year, month): # year est un int
                            ...
                        
Regex Complexes (re_path)

Pour des besoins très spécifiques (ex: ID hexadécimal de longueur fixe).

                            from django.urls import re_path

                            # Match IDs de 4 caractères alphanumériques
                            re_path(r'^sku/(?P<sku>[0-9a-f]{4})/$', views.sku_detail),
                        
Le problème des conflits

Si l'app "Blog" a une vue nommée detail et l'app "Shop" a aussi une vue nommée detail, comment faire un lien vers le bon détail ?

{% url 'detail' id=1 %} est ambigu !

La Solution : app_name

Définissez app_name dans le urls.py de chaque application.

                            # blog/urls.py
                            app_name = 'blog' # <--- ICI
                            urlpatterns = [
                            path('<int:pk>/', views.detail, name='detail'),
                            ]

                            # shop/urls.py
                            app_name = 'shop' # <--- ICI
                            urlpatterns = [
                            path('<int:pk>/', views.detail, name='detail'),
                            ]
                            
Utilisation

On utilise la syntaxe namespace:name.

  • Vers le blog : blog:detail
  • Vers le shop : shop:detail
                            Lire l'article
                            Acheter
                        
Le principe DRY (Don't Repeat Yourself)

Ne jamais écrire d'URLs en dur (ex: /blog/12/) dans votre code. Si l'URL change demain, vous devrez modifier 50 fichiers.

Laissez Django reconstruire l'URL à partir du nom de la vue et des paramètres.

Dans les Templates ({% url ... %})
                            Accueil

                            Voir

                            {% url 'shop:cart' as cart_url %}
                            {% if cart_url %}
                            Panier
                            {% endif %}
                        
Dans le Code Python (reverse)
                            from django.urls import reverse
                            from django.shortcuts import redirect

                            def my_view(request):
                            # 1. Générer l'URL en string
                            url = reverse('blog:detail', kwargs={'pk': 42})
                            # Résultat : "/blog/articles/42/"

                            # 2. Rediriger directement
                            return redirect('blog:list')

                            # 3. Dans les tests
                            response = self.client.get(reverse('home'))
                        
Astuce Pro : Utilisez get_absolute_url() dans vos Modèles. Cela permet d'appeler dans les templates sans se soucier de l'URLconf.
2.3 Templates, base.html et fichiers statiques
Organisation recommandée
templates/
                        base.html
                        core/
                        home.html
                        about.html
                        accounts/
                        login.html
                        profile.html
                        static/
                        css/app.css
                        js/app.js
                        img/logo.png
                    

On centralise les templates dans templates/ pour tout le projet.

Template de base
{%!DOCTYPE html%}
                        
                            
                                {% block title %}IDEO‑Lab{% endblock %}
                                
                            
                            
                                {% include "partials/navbar.html" %}
                                
{% block content %}{% endblock %}
Template d'une page
{% extends "base.html" %}
                        {% block title %}Accueil{% endblock %}
                        {% block content %}
                        

Bienvenue

Votre premier projet Django est fonctionnel.

{% endblock %}
Fichiers statiques

En production : python manage.py collectstatic pour copier tous les statiques dans STATIC_ROOT.

3.1 Modèles & ORM Django
Créer un modèle
# core/models.py
                        from django.db import models

                        class Article(models.Model):
                        title = models.CharField(max_length=200)
                        slug = models.SlugField(unique=True)
                        content = models.TextField()
                        created = models.DateTimeField(auto_now_add=True)
                        updated = models.DateTimeField(auto_now=True)

                        def __str__(self):
                        return self.title
Migrations
python manage.py makemigrations
                        python manage.py migrate
Utiliser l'ORM
from core.models import Article

                        # créer
                        Article.objects.create(title="Hello", slug="hello", content="Bienvenue")

                        # récupérer
                        art = Article.objects.get(slug="hello")

                        # filtrer
                        arts = Article.objects.filter(title__icontains="Django").order_by("-created")
                    
Dans une view
# core/views.py
                        from django.shortcuts import render
                        from .models import Article

                        def blog(request):
                        articles = Article.objects.all()
                        return render(request, "core/blog.html", {"articles": articles})
3.2 Connexion base de données (SQLite, PostgreSQL, MariaDB)
Par défaut : SQLite
DATABASES = {
                        "default": {
                        "ENGINE": "django.db.backends.sqlite3",
                        "NAME": BASE_DIR / "db.sqlite3",
                        }
                        }

Très bien pour débuter ou pour petites apps internes.

PostgreSQL
pip install psycopg2-binary
DATABASES = {
                        "default": {
                        "ENGINE": "django.db.backends.postgresql",
                        "NAME": "ideolab_db",
                        "USER": "ideolab_user",
                        "PASSWORD": "motdepasse",
                        "HOST": "127.0.0.1",
                        "PORT": "5432",
                        }
                        }
MariaDB / MySQL
pip install mysqlclient  # ou django-mysql
DATABASES = {
                        "default": {
                        "ENGINE": "django.db.backends.mysql",
                        "NAME": "ideolab_db",
                        "USER": "ideolab",
                        "PASSWORD": "xxx",
                        "HOST": "localhost",
                        "PORT": "3306",
                        "OPTIONS": {
                        "init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
                        }
                        }
                        }
Tests de connexion
python manage.py migrate
                        python manage.py dbshell  # selon driver
3.3 Interface d'administration Django
Activer un modèle
# core/admin.py
                        from django.contrib import admin
                        from .models import Article

                        @admin.register(Article)
                        class ArticleAdmin(admin.ModelAdmin):
                        list_display = ("title", "slug", "created", "updated")
                        search_fields = ("title", "content")
                        prepopulated_fields = {"slug": ("title",)}
                    

Créer un superuser :

python manage.py createsuperuser
Accès à /admin

L'admin est déjà branchée dans urls.py. On peut la styliser ou utiliser django-jazzmin pour un admin moderne.

pip install django-jazzmin
                        # puis ajouter "jazzmin" dans INSTALLED_APPS avant django.contrib.admin

L'admin est très utile pour prototyper des modèles.

4.1 Formulaires Django (Forms & ModelForm)
Form simple
# core/forms.py
                        from django import forms

                        class ContactForm(forms.Form):
                        name = forms.CharField(max_length=100)
                        email = forms.EmailField()
                        message = forms.CharField(widget=forms.Textarea)
                    
Dans la view
# core/views.py
                        from .forms import ContactForm

                        def contact(request):
                        form = ContactForm(request.POST or None)
                        if request.method == "POST" and form.is_valid():
                        # traiter ...
                        pass
                        return render(request, "core/contact.html", {"form": form})
ModelForm
# core/forms.py
                        from django.forms import ModelForm
                        from .models import Article

                        class ArticleForm(ModelForm):
                        class Meta:
                        model = Article
                        fields = ["title", "slug", "content"]
                    

Permet de générer un formulaire directement lié à un modèle.

4.2 Authentification & Permissions
Login / Logout
from django.contrib.auth import authenticate, login, logout
                        from django.shortcuts import render, redirect

                        def login_view(request):
                        if request.method == "POST":
                        u = request.POST.get("username")
                        p = request.POST.get("password")
                        user = authenticate(request, username=u, password=p)
                        if user is not None:
                        login(request, user)
                        return redirect("home")
                        return render(request, "accounts/login.html")

                        def logout_view(request):
                        logout(request)
                        return redirect("login")
Protéger une vue
from django.contrib.auth.decorators import login_required

                        @login_required
                        def dashboard(request):
                        ...
Permissions
from django.contrib.auth.decorators import permission_required

                        @permission_required("core.change_article")
                        def edit_article(request, pk):
                        ...
4.3 API Django (DRF rapide)
Installation DRF
pip install djangorestframework
# settings.py
                        INSTALLED_APPS += ["rest_framework"]
Serializer
# core/api/serializers.py
                        from rest_framework import serializers
                        from core.models import Article

                        class ArticleSerializer(serializers.ModelSerializer):
                        class Meta:
                        model = Article
                        fields = "__all__"
                    
ViewSet
# core/api/views.py
                        from rest_framework import viewsets
                        from .serializers import ArticleSerializer
                        from core.models import Article

                        class ArticleViewSet(viewsets.ModelViewSet):
                        queryset = Article.objects.all()
                        serializer_class = ArticleSerializer
                    
Routing
# core/api/urls.py
                        from rest_framework.routers import DefaultRouter
                        from .views import ArticleViewSet
                        router = DefaultRouter()
                        router.register("articles", ArticleViewSet)
                        urlpatterns = router.urls
5.1 Lancer le serveur de développement
Commande
python manage.py runserver
                        # ou spécifier le port
                        python manage.py runserver 0.0.0.0:8000

Utiliser ce serveur uniquement pour le développement.

Recharger automatiquement

Django recharge automatiquement quand un fichier Python change. Pour le frontend pur, utiliser aussi un watcher (npm/vite) si besoin.

5.2 Déployer Django avec Gunicorn (Linux)
Gunicorn – rôle

Gunicorn (Green Unicorn) est le serveur WSGI qui exécute Django. Nginx envoie les requêtes vers lui, il renvoie la réponse HTML/JSON.

Structure typique
/opt/ideo-lab/
                    ├── venv/
                    ├── ideolab_site/
                    ├── staticfiles/
                    └── media/
Lancer en manuel (débug)
cd /opt/ideo-lab
                    source venv/bin/activate
                    gunicorn ideolab_site.wsgi:application --bind 0.0.0.0:8001 --workers 3 --log-level info

Toujours tester d'abord en manuel. Si ça plante ici, ce n'est pas la peine de brancher Nginx.

Service systemd (classique)
# /etc/systemd/system/gunicorn_ideo.service
                            [Unit]
                            Description=Gunicorn daemon for IDEO‑Lab
                            After=network.target

                            [Service]
                            User=www-data
                            Group=www-data
                            WorkingDirectory=/opt/ideo-lab
                            EnvironmentFile=/opt/ideo-lab/.env
                            ExecStart=/opt/ideo-lab/venv/bin/gunicorn   --workers 4   --threads 2   --timeout 120   --bind unix:/run/gunicorn_ideo.sock   ideolab_site.wsgi:application
                            Restart=always

                            [Install]
                            WantedBy=multi-user.target
Service socket‑based
# /etc/systemd/system/gunicorn_ideo.socket
                            [Unit]
                            Description=Gunicorn IDEO‑Lab socket

                            [Socket]
                            ListenStream=/run/gunicorn_ideo.sock

                            [Install]
                            WantedBy=sockets.target
Commandes
sudo systemctl daemon-reload
                            sudo systemctl enable gunicorn_ideo
                            sudo systemctl start gunicorn_ideo
                            sudo systemctl status gunicorn_ideo

Si le socket n'existe pas → vérifier les permissions /run, l'utilisateur systemd et le chemin du venv.

Optimisation workers
# règle générale
                            workers = (2 * nombre_coeurs) + 1
                            threads = 2
                            timeout = 120

Exemple : serveur 4 vCPU → (2×4)+1 = 9 workers. Vérifier la RAM (100‑120 Mo / worker).

Tuning chemin Python
ExecStart=/opt/ideo-lab/venv/bin/gunicorn ...

Toujours pointer vers le binaire gunicorn du venv du projet.

Logging avancé
ExecStart=/opt/ideo-lab/venv/bin/gunicorn   --access-logfile /var/log/gunicorn/access.log   --error-logfile /var/log/gunicorn/error.log   ideolab_site.wsgi:application

Les logs Gunicorn peuvent être agrégés dans journald ou envoyés vers Loki/Promtail.

Monitoring
  • Module gunicorn --statsd-host=localhost:8125 pour exporter les métriques
  • Supervision via systemd-analyze ou htop
  • Surveillance du socket avec ss -lpt | grep gunicorn
Dépannage rapide
journalctl -u gunicorn_ideo -f
                    sudo systemctl restart gunicorn_ideo
                    sudo ss -lpt | grep gunicorn
Schéma
Nginx → (unix socket) → Gunicorn → Django → DB
5.3 Nginx en reverse proxy pour Django
Exemple simple (HTTP, socket local)
server {
                    listen 80;
                    server_name ideo-lab.com www.ideo-lab.com;

                    location = /favicon.ico { access_log off; log_not_found off; }

                    location /static/ {
                    root /opt/ideo-lab;
                    }

                    location /media/ {
                    root /opt/ideo-lab;
                    }

                    location / {
                    include proxy_params;
                    proxy_pass http://unix:/run/gunicorn_ideo.sock;
                    }
                    }
Activation
sudo ln -s /etc/nginx/sites-available/ideo-lab /etc/nginx/sites-enabled/
                    sudo nginx -t
                    sudo systemctl reload nginx
HTTPS avec Certbot (Let's Encrypt)
sudo apt install certbot python3-certbot-nginx
                    sudo certbot --nginx -d ideo-lab.com -d www.ideo-lab.com

Certbot crée automatiquement la configuration SSL et renouvelle les certificats.

Version complète HTTPS
server {
                    listen 443 ssl http2;
                    server_name ideo-lab.com www.ideo-lab.com;

                    ssl_certificate /etc/letsencrypt/live/ideo-lab.com/fullchain.pem;
                    ssl_certificate_key /etc/letsencrypt/live/ideo-lab.com/privkey.pem;
                    ssl_protocols TLSv1.2 TLSv1.3;
                    ssl_ciphers HIGH:!aNULL:!MD5;
                    add_header Strict-Transport-Security "max-age=31536000" always;

                    client_max_body_size 50M;
                    keepalive_timeout 65;

                    access_log /var/log/nginx/ideo_access.log;
                    error_log  /var/log/nginx/ideo_error.log;

                    location /static/ {
                    alias /opt/ideo-lab/staticfiles/;
                    expires 1y;
                    add_header Cache-Control "public, immutable";
                    }
                    location /media/ {
                    alias /opt/ideo-lab/media/;
                    }
                    location / {
                    proxy_pass http://unix:/run/gunicorn_ideo.sock;
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto $scheme;
                    proxy_read_timeout 600s;
                    proxy_connect_timeout 600s;
                    }
                    }
Redirection HTTP → HTTPS
server {
                    listen 80;
                    server_name ideo-lab.com www.ideo-lab.com;
                    return 301 https://$host$request_uri;
                    }
Multi‑site (plusieurs projets Django)
# /etc/nginx/sites-available/
                    ├── ideo-lab.conf
                    ├── blog.conf
                    └── api.conf

Chaque site utilise son propre socket Gunicorn : /run/gunicorn_blog.sock, /run/gunicorn_api.sock. On peut mutualiser les logs et les certificats via certbot --expand.

Reverse proxy + cache (avancé)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=24h;
                    server {
                    location /static/ {
                    proxy_cache STATIC;
                    proxy_cache_valid 200 302 10m;
                    proxy_cache_valid 404 1m;
                    proxy_pass http://unix:/run/gunicorn_ideo.sock;
                    }
                    }
Diagnostic & maintenance
  • sudo nginx -t pour valider la config
  • sudo systemctl reload nginx pour recharger sans coupure
  • sudo tail -f /var/log/nginx/access.log pour suivre les requêtes
  • sudo journalctl -u nginx pour logs système
Schéma du flux
Client HTTPS
                    │
                    ▼
                    Nginx (TLS, static, cache)
                    │
                    ▼
                    Gunicorn (WSGI)
                    │
                    ▼
                    Django ORM → PostgreSQL/MariaDB
5.4 Déployer Django sous Windows (WAMP / Apache)
Contexte

Sous Windows, on peut garder le serveur de dev, mais pour une intégration avec Apache on utilisera mod_wsgi.

Installer mod_wsgi pour Windows

Télécharger la version compatible avec Apache + Python, puis ajouter dans httpd.conf.

LoadModule wsgi_module modules/mod_wsgi.so
                        WSGIPythonHome "C:/path/to/venv/"
VirtualHost

                            ServerName django.local
                            WSGIScriptAlias / C:/projects/ideo-lab/ideolab_site/wsgi.py
                            
                                
                                    Require all granted
                                
                            
                            Alias /static/ C:/projects/ideo-lab/static/
                            
                                Require all granted
                            
                        

Moins courant qu'un déploiement Linux, mais utile en environnement 100% Windows.

6.1 Sécurité, .env, logs & Sentry
Variables d'environnement

Ne jamais mettre les mots de passe dans settings.py. Utiliser python-dotenv ou l'environnement systemd.

pip install python-dotenv
from dotenv import load_dotenv
                    import os
                    load_dotenv()
                    SECRET_KEY = os.getenv("DJANGO_SECRET_KEY")
                    DEBUG = os.getenv("DJANGO_DEBUG", "False") == "True"
Exemple de .env
DJANGO_SECRET_KEY=...long...
                    DJANGO_DEBUG=False
                    ALLOWED_HOSTS=ideo-lab.com,www.ideo-lab.com
                    DATABASE_URL=postgres://user:pass@localhost:5432/ideo_lab
                    SENTRY_DSN=https://xxxxx.ingest.sentry.io/xxxx
Gestion des secrets sur le serveur
sudo mkdir /opt/ideo-lab/secrets
                    sudo chown www-data:www-data /opt/ideo-lab/secrets
                    sudo chmod 600 /opt/ideo-lab/secrets
Paramètres de sécurité Django
DEBUG = False
                    ALLOWED_HOSTS = ["ideo-lab.com", "www.ideo-lab.com"]
                    CSRF_COOKIE_SECURE = True
                    SESSION_COOKIE_SECURE = True
                    SECURE_SSL_REDIRECT = True
                    SECURE_HSTS_SECONDS = 31536000
                    SECURE_HSTS_INCLUDE_SUBDOMAINS = True
                    SECURE_HSTS_PRELOAD = True
                    SECURE_CONTENT_TYPE_NOSNIFF = True
                    X_FRAME_OPTIONS = "DENY"
CSP (Content Security Policy)
class CSPMiddleware:
                    def __init__(self, get_response):
                    self.get_response = get_response
                    def __call__(self, request):
                    resp = self.get_response(request)
                    resp["Content-Security-Policy"] = "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'"
                    return resp
Logging multi‑niveau
LOGGING = {
                    "version": 1,
                    "disable_existing_loggers": False,
                    "formatters": {
                    "verbose": {
                    "format": "[{asctime}] {levelname} {name}: {message}",
                    "style": "{",
                    },
                    },
                    "handlers": {
                    "file": {
                    "class": "logging.FileHandler",
                    "filename": BASE_DIR / "logs/django_info.log",
                    "formatter": "verbose",
                    },
                    "error_file": {
                    "class": "logging.FileHandler",
                    "filename": BASE_DIR / "logs/django_errors.log",
                    "formatter": "verbose",
                    },
                    },
                    "loggers": {
                    "django": {
                    "handlers": ["file"],
                    "level": "INFO",
                    "propagate": True,
                    },
                    "django.request": {
                    "handlers": ["error_file"],
                    "level": "ERROR",
                    "propagate": False,
                    },
                    },
                    }
Audit cron
#!/bin/bash
                    CONF="/opt/ideo-lab/ideolab_site/settings.py"
                    LOG="/opt/ideo-lab/logs/security_audit.log"
                    grep -q "DEBUG = True" $CONF && echo "$(date) - ALERT: DEBUG activé" >> $LOG
                    find /opt/ideo-lab/logs/ -size +50M -type f -exec echo "$(date) - Log volumineux: {}" \; >> $LOG
Intégration Sentry
pip install sentry-sdk
import sentry_sdk
                    from sentry_sdk.integrations.django import DjangoIntegration

                    sentry_sdk.init(
                    dsn=os.getenv("SENTRY_DSN"),
                    integrations=[DjangoIntegration()],
                    traces_sample_rate=0.3,
                    send_default_pii=True,
                    )

Toutes les erreurs de production sont alors visibles dans le dashboard Sentry (avec user, URL, stacktrace).

6.2 Optimisation & maintenance
Collecte des statiques
python manage.py collectstatic

À lancer après chaque déploiement si tu as modifié les fichiers statiques.

Maintenance DB
python manage.py showmigrations
                        python manage.py migrate
                        python manage.py clearsessions
Supervision

Sur Linux : superviser gunicorn et nginx (systemd). Ajouter un healthcheck.

Cache
CACHES = {
                        "default": {
                        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
                        "LOCATION": "unique-snowflake",
                        }
                        }
6.3 Déploiement complet IDEO‑Lab Django
Arbo serveur (Ubuntu)
/opt/ideo-lab/
                        venv/
                        ideolab_site/
                        staticfiles/
                        media/
                        /etc/systemd/system/gunicorn_ideo.service
                        /etc/nginx/sites-available/ideo-lab
                    
Pipeline
git pull origin main
                        source venv/bin/activate
                        pip install -r requirements.txt
                        python manage.py migrate
                        python manage.py collectstatic --noinput
                        sudo systemctl restart gunicorn_ideo
                        sudo systemctl restart nginx
Schéma de flux
Client (HTTPS)
                        │
                        ▼
                        Nginx (SSL, static, media)
                        │  proxy_pass
                        ▼
                        Gunicorn (WSGI, Django)
                        │
                        ▼
                        Django → ORM → DB (PostgreSQL/MariaDB)
                    

On peut ensuite automatiser avec GitHub Actions ou un cron qui fait le pull + reload.

7.1 Cheat‑sheet Django (commandes rapides)
Commandes les plus utiles
django-admin startproject proj .
                        python manage.py startapp app
                        python manage.py runserver
                        python manage.py makemigrations
                        python manage.py migrate
                        python manage.py createsuperuser
                        python manage.py shell
                        python manage.py collectstatic
                    
Outils debug
pip install django-debug-toolbar
# settings.py
                        INSTALLED_APPS += ["debug_toolbar"]
                        MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")

Très utile en dev pour voir les requêtes SQL.

Django Static Analyzer : Cross-Reference Check
Le concept

Les erreurs NoReverseMatch sont la cause #1 des crashs en prod (erreur 500).

Cet outil croise :

  • Les {% url 'name' %} dans les templates.
  • Les path(name='...') dans urls.py.
Démo Live :
Utilisez le simulateur à droite pour tester la logique. Copiez le script Python pour l'utiliser en local.

En attente de l'analyse...