Louis Mazin 63496f1c2a nickel
2026-10-15 15:05:26 +02:00
2026-10-15 15:05:26 +02:00
2026-10-15 15:05:26 +02:00
2026-10-15 14:17:25 +02:00
2026-10-15 14:17:25 +02:00
2026-10-15 14:17:25 +02:00
2026-10-15 14:52:54 +02:00
2026-10-15 14:52:54 +02:00

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

  1. Compléter les secrets du .env (ou les générer avec python scripts/init_env.py).
  2. Modifier si nécessaire FRONTEND_PORT, BACKEND_PORT, ALLOWED_HOSTS et les origines autorisées.
  3. 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.

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 volume db_data (non exposé sur le réseau hôte).
  • backend : Django + Gunicorn sur le port interne 8000, publié sur BACKEND_PORT.
  • frontend : React compilé puis servi par Nginx sur le port interne 80, publié sur FRONTEND_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 dans INSTALLED_APPS et ses URL dans core/urls.py.
  • React : nouvelles pages dans frontend/src/pages/, hooks dans hooks/ et appels à l’API dans services/. Ne pas appeler fetch dans les composants JSX.
  • shadcn/ui : le fichier components.json est 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.example et les lire via decouple.config cô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_PASSWORD et ADMIN_PASSWORD sont 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_staff accè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.js centralise 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.

Description
No description provided
Readme 82 KiB
Languages
JavaScript 56.7%
Python 33.1%
Shell 4.3%
CSS 4.1%
Dockerfile 1.2%
Other 0.6%