9.7 KiB
Template Django + React + MySQL
Un squelette réutilisable inspiré de l'organisation de GoodDrive, sans ses fonctionnalités : Django REST Framework, React/Vite, Tailwind 4, composants shadcn/ui, Oxlint, MySQL 8 et Docker Compose.
Démarrage rapide
- Compléter les secrets du
.env(ou les générer avecpython scripts/init_env.py). - Modifier si nécessaire
FRONTEND_PORT,BACKEND_PORT,ALLOWED_HOSTSet les origines autorisées. - Démarrer avec le script principal :
chmod +x start.sh
./start.sh
start.sh initialise le .env, puis détecte Docker Compose. Si Docker est disponible,
il construit et démarre les trois services. Sinon, il lance Django et React dans le même
environnement (mode Pterodactyl, avec une base MySQL externe déjà accessible).
Tu peux choisir explicitement :
./start.sh --compose # Docker Compose
./start.sh --standalone # Un seul environnement, sans Docker
En mode standalone, Python 3, Node.js/npm et les bibliothèques nécessaires à mysqlclient
doivent être disponibles. Le script installe les dépendances Python manquantes, installe
les dépendances React et compile le frontend avant de lancer les deux serveurs.
La variable MYSQL_HOST=db du modèle fonctionne uniquement en mode Compose :
en mode standalone, indique l'adresse réelle de ton serveur MySQL dans .env.
Le mode standalone utilise vite preview pour servir le build et le proxy API ; pour
un site public à forte charge, préfère le mode Docker Compose avec Nginx.
Le script ne télécharge ni n'écrase automatiquement le dépôt Git.
- Frontend : http://localhost:1028 (ou
FRONTEND_PORT) - Backend : http://localhost:1029/api/health/ (ou
BACKEND_PORT) - Administration React (shadcn/ui) : http://localhost:1028/admin/
- Admin Django technique : http://localhost:1028/django-admin/
Au premier lancement, ensure_admin crée le compte à partir de ADMIN_*. Si le compte existe déjà, il ne change pas son mot de passe à chaque redémarrage.
Attention : ne versionne jamais .env, et remplace les noms/mots de passe par des valeurs propres à chaque projet. DEBUG=True ne doit pas être utilisé en production.
Structure
.
├── .env # paramètres locaux, non versionné
├── .env.example # modèle sans secrets
├── docker-compose.yml
├── start.sh # Démarrage Compose ou standalone / Pterodactyl
├── scripts/
│ └── init_env.py
├── backend/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ ├── requirements.txt
│ ├── manage.py
│ ├── core/
│ │ ├── settings.py
│ │ ├── origins.py
│ │ └── urls.py
│ └── common/
│ ├── urls.py
│ ├── views.py
│ ├── admin_api.py # API sécurisée pour le tableau de bord React
│ └── management/commands/ensure_admin.py
└── frontend/
├── Dockerfile
├── nginx.conf
├── package.json
├── .oxlintrc.json # Oxlint : JS/JSX, React et accessibilité
├── components.json
├── vite.config.js
└── src/
├── App.jsx # sélection des pages
├── index.css
├── pages/ # HomePage, AdminPage
├── hooks/ # logique React et états réutilisables
├── services/ # appels HTTP centralisés, AUCUN fetch dans JSX
│ ├── apiClient.js
│ ├── healthService.js
│ ├── authService.js
│ └── adminService.js
└── components/
├── admin/ # widgets de la page d'administration
├── layout/ # composants partagés
└── ui/ # composants shadcn/ui
Origines CORS/CSRF et ports automatiques
backend/core/settings.py transforme les origines du .env automatiquement.
FRONTEND_PORT=1028
BACKEND_PORT=1029
CORS_ALLOWED_ORIGINS=http://localhost,http://127.0.0.1
CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1
Valeurs effectives :
CORS_ALLOWED_ORIGINS = ["http://localhost:1028", "http://127.0.0.1:1028"]
CSRF_TRUSTED_ORIGINS = [
"http://localhost:1029", "http://127.0.0.1:1029", # backend
"http://localhost:1028", "http://127.0.0.1:1028", # frontend
]
Les origines comportant déjà un port explicite sont conservées telles quelles :
http://localhost:3000 reste http://localhost:3000.
Pour un reverse proxy HTTPS avec ports standards 443, mets AUTO_PORT_CORS=False et
AUTO_PORT_CSRF=False, puis indique tes origines complètes dans les deux variables.
Cela évite d'ajouter :1028 à https://mon-domaine.fr.
Pourquoi le frontend figure également dans CSRF ? Django en a besoin pour les formulaires avec cookie/session provenant de l'interface. Cela complète la règle demandée « port backend pour CSRF, port frontend pour CORS ».
Dans ce template, le frontend utilise /api/ sur le même domaine grâce au proxy Nginx :
CORS n'est normalement pas nécessaire pour la communication interne, mais reste
configuré si une autre application appelle directement l'API exposée sur le port backend.
Architecture Docker
db: MySQL 8.4 avec volumedb_data(non exposé sur le réseau hôte).backend: Django + Gunicorn sur le port interne 8000, publié surBACKEND_PORT.frontend: React compilé puis servi par Nginx sur le port interne 80, publié surFRONTEND_PORT.- Nginx relaie
/api/,/django-admin/et/static/vers Django./admin/est une page React.
Le port MYSQL_PORT est le port de MySQL dans le réseau des conteneurs (3306 avec le service db). Pour une base distante, adapte MYSQL_HOST et MYSQL_PORT. Le service db reste créé par Compose dans cette version du template.
Ajouter tes fonctionnalités
- Django : nouvelle application via
python manage.py startapp monapp; l'ajouter dansINSTALLED_APPSet ses URL danscore/urls.py. - React : nouvelles pages dans
frontend/src/pages/, hooks danshooks/et appels à l’API dansservices/. Ne pas appelerfetchdans les composants JSX. - shadcn/ui : le fichier
components.jsonest présent. Ajouter les composants via la CLI shadcn (npx shadcn@latest add dialog, par exemple). Le template inclut Button, Card, Input, Label, Table, Badge, Dialog, Separator et Alert. - Variables supplémentaires : les ajouter au
.env.exampleet les lire viadecouple.configcôté Django.
Qualité du code avec Oxlint
Oxlint est inclus dans les dépendances de développement du frontend. Il contrôle le JavaScript/JSX, les règles React, les erreurs fréquentes et certaines règles d’accessibilité. Il ne remplace pas un formateur de code.
cd frontend
npm install
npm run lint # Contrôle sans modifier les fichiers
npm run lint:fix # Applique les corrections automatiques sûres disponibles
La configuration se trouve dans frontend/.oxlintrc.json. Les dossiers dist et coverage sont ignorés. Oxlint est volontairement indépendant du démarrage : start.sh ne bloque pas le lancement du site sur un avertissement de lint.
Vérifier et exploiter
# Logs
docker compose logs -f backend
docker compose logs -f frontend
# Voir les origines effectives (ne pas afficher le SECRET_KEY)
docker compose exec backend python manage.py shell -c "from django.conf import settings; print(settings.CORS_ALLOWED_ORIGINS, settings.CSRF_TRUSTED_ORIGINS)"
# Tests unitaires des origines (sans Django)
cd backend && python -m unittest discover -s tests
# Avec une base Django de test :
python manage.py test common
# Stopper sans détruire MySQL
docker compose down
Ne pas utiliser docker compose down -v : cela supprime le volume de la base.
Notes de sécurité
SECRET_KEY,MYSQL_PASSWORD,MYSQL_ROOT_PASSWORDetADMIN_PASSWORDsont générés localement par le script, sans être publiés dans le ZIP.- Les identifiants MySQL ne sont pas intégrés dans les images Docker.
- La route de diagnostic
/api/health/est volontairement publique ; les futures routes API sont protégées par défaut dans DRF. - Sur Internet, configure HTTPS,
ALLOWED_HOSTS, origines, cookies sécurisés et reverse proxy avant mise en ligne. - En production, évite d'exposer directement le port backend si les appels passent seulement par Nginx.
Tableau de bord administrateur (shadcn/ui)
/admin/: interface React avec connexion par session Django, thème clair/sombre, statistiques, recherche, création de comptes et activation/désactivation./django-admin/: administration Django native conservée pour la gestion avancée.- Seuls les comptes
is_staffaccèdent au tableau de bord. Pour créer ou désactiver des comptes, il faut en plus être superutilisateur. Le compte connecté et les autres superutilisateurs sont protégés contre la désactivation. - L'API se trouve dans
backend/common/admin_api.py. La session Django et les jetons CSRF protègent les actions, les secrets ne sont jamais stockés dans le frontend. - Le frontend parle au backend par un chemin relatif
/api/, proxifié en Compose comme en standalone.frontend/src/services/apiClient.jscentralise les erreurs, cookies et en-têtes CSRF. - L'interface ne remplace pas les permissions fines de Django Admin pour les modèles que tu ajouteras : la page React sert de base claire et extensible.
Validation
Le template inclut les tests backend/common/tests.py pour l'authentification,
les autorisations administrateur et la CSRF. Pour les lancer, une base Django de test
accessible est requise : python manage.py test common.