Chapo. Fini les “ça marche chez moi”. En basculant votre poste de travail vers un IDE cloud et des conteneurs reproductibles, vous standardisez le dev, sécurisez les secrets et rapprochez enfin le quotidien de la production. Voici l’introduction structurée pour bien démarrer un projet Django en ligne, avec une architecture claire, des settings 12-Factor et des variables d’environnement bien tenues.
La diversité des machines et des habitudes fragilise la qualité. Un environnement hébergé (Codespaces, Gitpod, ou tout IDE cloud équivalent) égalise les versions, accélère l’onboarding et simplifie les revues. Résultat : moins de frictions, plus de focus sur le produit, et une parité dev-prod qui limite les surprises au déploiement.
Un projet lisible commence par une intention : un dossier src/ qui contient le code applicatif, un paquet config/ pour les settings/ASGI/WSGI/urls, un répertoire apps/ pour vos applications métier, et des espaces dédiés aux templates, static et tests. Cette topologie évite les collisions d’import, clarifie les responsabilités et prépare la CI/CD.
Le cœur des erreurs de déploiement se niche dans les réglages. On isole l’invariant dans base.py, et l’on superpose dev.py et prod.py pour activer le confort de dev ou les garde-fous de sécurité. Clé secrète, base de données, cache, email, niveau de logs : tout provient de l’environnement, jamais du code.
Les env vars sont votre contrat avec l’infrastructure. Un .env.example documente les clés attendues (sans secrets), tandis que les secrets réels vivent côté coffre (IDE, plateforme, CI). On y place DJANGO_SECRET_KEY, DATABASE_URL, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, DJANGO_LOG_LEVEL, etc. Le code lit l’environnement, la plateforme injecte les valeurs.
Sur un IDE cloud, la routine est simple : installer les dépendances, exporter DJANGO_SETTINGS_MODULE=config.settings.dev, exécuter migrate puis runserver 0.0.0.0:8000. On ajoute l’URL de prévisualisation aux hôtes autorisés et aux origines CSRF, et l’équipe voit la même chose, au même endroit, au même moment.
Le conteneur n’est pas un disque. Les fichiers utilisateurs (MEDIA) partent vers un stockage persistant ; les statiques sont collectés en prod (Whitenoise/CDN) ; les sessions et caches reposent sur des services gérés (DB/Redis). Les logs sortent en flux vers stdout/stderr pour être agrégés proprement. Ce choix “stateless” assure l’élasticité sans dettes cachées.
HTTPS activé, cookies sécurisés, HSTS, URL d’admin discrète, 2FA, CORS/CSRF en liste blanche, et revue systématique des secrets. En ligne comme en prod, la surface d’attaque diminue quand la configuration est stricte et centralisée dans l’environnement.
Onboarding en minutes, exécution cohérente entre dev et prod, diagnostics facilités par des logs normalisés, et une architecture prête pour web/worker/scheduler. Vous codez, testez, déployez—sans “magie” locale ni écarts non maîtrisés.
Un environnement Django en ligne devient un multiplicateur de vitesse quand la structure, les settings 12-Factor et les env vars sont cadrés dès le départ. Vous gagnez en reproductibilité, en sécurité et en sérénité de déploiement.
Objectif. Passer de l’intention à l’exécution : un projet Django en ligne prêt à coder, tester et déployer, avec une structure nette, des settings 12-Factor, et des env vars maîtrisées.
Rituel de base
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install django dj-database-url python-dotenv
mkdir -p src && cd src
django-admin startproject config .
django-admin startapp core apps/core
Arborescence de référence
project-root/
├─ .gitignore
├─ .env.example
├─ pyproject.toml # ou requirements.txt / constraints.txt
├─ devcontainer.json # optionnel (IDE cloud / VS Code)
├─ docker/ # optionnel (Dockerfiles/scripts)
├─ manage.py
├─ src/
│ ├─ config/
│ │ ├─ asgi.py
│ │ ├─ wsgi.py
│ │ └─ settings/
│ │ ├─ base.py
│ │ ├─ dev.py
│ │ └─ prod.py
│ ├─ apps/core/
│ ├─ templates/
│ └─ static/
└─ tests/
Pourquoi src/ ? Pour éviter les collisions d’import et séparer outils/CI du code métier.
base.py : l’invariant
# src/config/settings/base.py
from pathlib import Path
import os
import dj_database_url
BASE_DIR = Path(__file__).resolve().parents[2] # .../project-root
def env(key, default=None, cast=str):
val = os.getenv(key, default)
return cast(val) if (val is not None and cast and cast is not str) else val
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "change-me") # jamais en prod
DEBUG = os.getenv("DJANGO_DEBUG", "0") == "1"
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "").split(",") if os.getenv("DJANGO_ALLOWED_HOSTS") else []
CSRF_TRUSTED_ORIGINS = os.getenv("DJANGO_CSRF_TRUSTED_ORIGINS", "").split(",") if os.getenv("DJANGO_CSRF_TRUSTED_ORIGINS") else []
LANGUAGE_CODE = os.getenv("DJANGO_LANGUAGE_CODE", "fr-fr")
TIME_ZONE = os.getenv("DJANGO_TIME_ZONE", "Europe/Paris")
USE_I18N = True
USE_TZ = True
INSTALLED_APPS = [
"django.contrib.admin","django.contrib.auth","django.contrib.contenttypes",
"django.contrib.sessions","django.contrib.messages","django.contrib.staticfiles",
"apps.core",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "config.urls"
WSGI_APPLICATION = "config.wsgi.application"
ASGI_APPLICATION = "config.asgi.application"
DATABASES = {"default": dj_database_url.parse(os.getenv("DATABASE_URL","sqlite:///db.sqlite3"))}
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
LOGGING = {
"version": 1, "disable_existing_loggers": False,
"handlers": {"console": {"class": "logging.StreamHandler"}},
"root": {"handlers": ["console"], "level": os.getenv("DJANGO_LOG_LEVEL","INFO")},
}
Overlays
# src/config/settings/dev.py
from .base import *
DEBUG = True
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")
# src/config/settings/prod.py
from .base import *
SECURE_SSL_REDIRECT = os.getenv("DJANGO_SSL_REDIRECT","1") == "1"
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = int(os.getenv("DJANGO_HSTS_SECONDS","0"))
Sélection à l’exécution
export DJANGO_SETTINGS_MODULE=config.settings.dev # ou prod
.env.example (versionné, sans secrets)
DJANGO_SECRET_KEY=changeme
DJANGO_DEBUG=1
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost:8000
DJANGO_LOG_LEVEL=INFO
DJANGO_LANGUAGE_CODE=fr-fr
DJANGO_TIME_ZONE=Europe/Paris
DATABASE_URL=sqlite:///db.sqlite3
# DATABASE_URL=postgres://USER:PASS@HOST:5432/DBNAME
DJANGO_SSL_REDIRECT=0
DJANGO_HSTS_SECONDS=0
Bonnes pratiques
.env.example, ignorer .env.Routine
pip install -r requirements.txt # ou: poetry install
export DJANGO_SETTINGS_MODULE=config.settings.dev
python manage.py migrate
python manage.py runserver 0.0.0.0:8000
Détails qui évitent les pièges
pyproject.toml minimal
[tool.black]
line-length = 100 [tool.isort]
profile = « black »
[tool.ruff]
line-length = 100 select = [« E », »F », »I », »UP »]
pre-commit (extrait)
repos:
- repo: https://github.com/psf/black
rev: 24.8.0
hooks: [{id: black}]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.6.9
hooks: [{id: ruff}]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: detect-private-key
Tests
pip install pytest pytest-django coverage
pytest -q
Procfile (exemple Heroku-like)
web: gunicorn config.wsgi:application --bind 0.0.0.0:$PORT
worker: celery -A config worker -l info
beat: celery -A config beat -l info
Réglez les env vars séparément (ex. CELERY_BROKER_URL, REDIS_URL) ; ne mélangez pas les commandes dans un seul process.
docker-compose.yml de dev
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
env_file: .env
environment:
- DJANGO_SETTINGS_MODULE=config.settings.dev
volumes:
- .:/app
ports: ["8000:8000"]
depends_on: [db, redis]
db:
image: postgres:16
environment:
POSTGRES_USER: django
POSTGRES_PASSWORD: django
POSTGRES_DB: django
ports: ["5432:5432"]
redis:
image: redis:7
ports: ["6379:6379"]
Ajustement côté settingsDATABASE_URL=postgres://django:django@db:5432/django et un cache/broker pointés sur redis://redis:6379/0.
collectstatic en phase build.DJANGO_LOG_LEVEL, agrégation côté plateforme.DJANGO_SSL_REDIRECT=1), HSTS en prod.pip ou poetry).DJANGO_SETTINGS_MODULE=config.settings.dev.migrate puis runserver 0.0.0.0:8000.pytest) et vérifier lint.CSRF_TRUSTED_ORIGINS.ALLOWED_HOSTS.DJANGO_LOG_LEVEL et l’agrégateur de la plateforme.collectstatic, empaqueter l’image.pytest, ruff, black --check.manage.py migrate).
Quand on finance une voiture, tout le monde voit à peu près de quoi il…
On connaît tous ce moment : on tombe sur une offre de leasing “à partir…
Dans l’industrie, parler de maintenance sans préciser le niveau d’intervention revient souvent à créer de…
La Maintenance 1er Niveau - maintenance de niveau 1 - représente la première barrière contre…
Un outil simple pour mesurer la compréhension… et révéler les écarts invisibles Dans beaucoup d’organisations,…
Le levier discret qui transforme l’image, la cohésion et la performance d’une organisation Dans beaucoup…
This website uses cookies.