# 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 : ```sh 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 : ```sh ./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 ```text . ├── .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. ```ini 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 : ```python 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. ```sh 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 ```sh # 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`.