Starter 3 — Carnet de contacts¶
Starter Forge · Niveau 3
Carnet de contacts
Un carnet relationnel simple : `Ville`, `Contact`, relation `many_to_one`, formulaire avec sélection et SQL visible en `LEFT JOIN`.
-
Objectif
Comprendre une relation Forge V1 sans ORM implicite.
-
Génération
Disponible avec
forge starter:build 3. -
Modèle
Deux entités, une relation globale, un SQL de relation visible.
-
Résultat
Contacts liés optionnellement à une ville.
Génération automatique disponible
Ce starter est générable avec forge starter:build 3, forge starter:build carnet ou forge starter:build carnet-contacts.
Périmètre actuel
La génération automatique crée Ville, Contact et la relation Contact.ville_id -> Ville.id. Elle ne génère pas encore Groupe, ContactGroupe ni de many-to-many explicite.
Prérequis¶
Prérequis généraux¶
- Python 3.11 ou supérieur
- Git
pipx(recommandé) ou environnement virtuel Python- MariaDB installé et démarré
- Accès à un compte administrateur MariaDB (pour
forge db:init) - Fichier
env/devconfiguré avec les identifiants MariaDB
Prérequis spécifiques au starter¶
- Starters 1 et 2 compris, ou au moins le cycle entité → SQL → CRUD
- Projet Forge vierge, ou scaffold adoptable (le starter détecte et adopte un
relations.jsonvide) - Support des relations Forge :
relations.jsonetrelations.sql(générés automatiquement) - Utiliser
--forceuniquement si le starter est déjà partiellement présent dans le projet
Partie 1 — Installer Forge sur une VM Debian vierge¶
Si Forge est déjà installé et configuré sur votre machine, passez directement à la Partie 2 — Construire l'application starter.
La procédure complète est documentée sur la page Installation sur VM Debian vierge.
Elle couvre en 7 étapes : mise à jour du système, dépendances Python/MariaDB, Node.js optionnel, configuration de pipx, démarrage de MariaDB, vérification de l'accès administrateur et installation de Forge via pipx.
Une fois que forge --version s'affiche correctement, revenez ici pour construire l'application.
Partie 2 — Construire l'application starter¶
Présentation rapide¶
Le starter construit une application de carnet de contacts avec :
- une liste de contacts enrichie par leur ville ;
- un formulaire Contact avec
<select name="ville_id">; - une page détail Contact ;
- une liste simple des villes ;
- un script de seed pour les villes de test ;
- des requêtes SQL visibles dans le modèle applicatif.
flowchart LR
A["Contact"] -->|"ville_id nullable"| B["Ville"]
C["contact_model.py"] -->|"LEFT JOIN visible"| A
C --> B
D["relations.json"] -->|"many_to_one"| A
Générer le starter¶
Depuis un projet Forge vierge ou préparé :
Vérifier d'abord que env/dev contient les identifiants administrateur MariaDB :
Compte administrateur MariaDB
La procédure utilise root avec mot de passe. Pour un environnement plus sécurisé, remplacer root par un compte dédié, par exemple forge_admin.
forge doctor
forge starter:build 3 --dry-run
forge starter:build 3 --init-db
python scripts/seed_villes.py
Alias équivalents :
--init-db lance explicitement l'initialisation MariaDB. Sans cette option, la base doit déjà être prête.
--force reconstruit les fichiers du starter 3 et le bloc de routes marqué. Il préserve les fichiers manuels d'entité comme contact.py, ville.py et les __init__.py existants.
Modèle généré¶
Entités :
Relation globale :
Colonnes SQL importantes :
| Entité | Champs Python | Colonnes SQL |
|---|---|---|
Ville |
id, nom, code_postal |
VilleId, Nom, CodePostal |
Contact |
id, nom, prenom, email, telephone, ville_id |
ContactId, Nom, Prenom, Email, Telephone, VilleId |
ville_id est nullable pour permettre :
JSON Et Relations¶
Le starter injecte deux JSON canoniques :
Il injecte aussi la source canonique relationnelle :
Forge génère ensuite :
Relation générée
SQL Visible¶
Le modèle mvc/models/contact_model.py utilise une jointure visible :
SELECT
contact.ContactId,
contact.Nom,
contact.Prenom,
contact.Email,
contact.Telephone,
contact.VilleId,
ville.Nom AS VilleNom,
ville.CodePostal AS VilleCodePostal
FROM contact
LEFT JOIN ville ON ville.VilleId = contact.VilleId
ORDER BY contact.Nom, contact.Prenom
Il n'y a pas d'ORM implicite : le modèle applicatif porte explicitement les requêtes nécessaires à l'écran.
Fichiers Créés¶
mvc/entities/ville/
mvc/entities/contact/
mvc/entities/relations.json
mvc/entities/relations.sql
mvc/controllers/contact_controller.py
mvc/controllers/ville_controller.py
mvc/models/contact_model.py
mvc/models/ville_model.py
mvc/forms/contact_form.py
mvc/views/layouts/app.html
mvc/views/contact/index.html
mvc/views/contact/form.html
mvc/views/contact/show.html
mvc/views/ville/index.html
scripts/seed_villes.py
Routes¶
GET /contacts
GET /contacts/new
POST /contacts
GET /contacts/{id}
GET /contacts/{id}/edit
POST /contacts/{id}
POST /contacts/{id}/delete
GET /villes
Les routes sont injectées entre marqueurs :
Elles sont publiques et sans CSRF automatique, car ce starter ne met pas en place d'authentification ni de session utilisateur.
Choix pédagogique — pas une bonne pratique générale
Le starter 3 est volontairement public pour rester centré sur les relations entre entités. Il ne traite pas encore l'authentification.
Dans une application réelle, les routes d'écriture (POST /contacts, POST /contacts/{id}, POST /contacts/{id}/delete, POST /villes) devront être protégées et la protection CSRF conservée.
Données De Test¶
Après génération :
Le script insère de manière idempotente :
| Ville | Code postal |
|---|---|
| Dreux | 28100 |
| Chartres | 28000 |
| Paris | 75000 |
| Lyon | 69000 |
| Nantes | 44000 |
Vérification finale¶
Ouvrir :
Tester :
- créer un contact avec ville ;
- afficher son détail ;
- modifier sa ville ;
- supprimer le contact ;
- vérifier la liste des villes.
Suite pédagogique¶
Le many-to-many explicite avec Groupe et ContactGroupe reste une évolution possible du parcours. Il doit rester modélisé par une entité pivot explicite et deux relations many_to_one, pas par une magie ORM.
Reconstruction¶
Le fichier court de reconstruction est disponible dans starters/03-carnet-contacts/rebuild.md.
Dépannage rapide¶
| Erreur | Cause probable | Correction |
|---|---|---|
forge: command not found |
pipx n'est pas dans le PATH |
pipx ensurepath puis exec $SHELL -l |
No module named venv |
python3-venv absent |
sudo apt install python3-venv |
mariadb_config not found |
dépendances MariaDB dev absentes | sudo apt install libmariadb-dev pkg-config |
Access denied for user 'root'@'localhost' |
mauvais mot de passe root ou root configuré en unix_socket |
vérifier le mot de passe, ou tester sudo mariadb |
mariadb: command not found |
client MariaDB absent | sudo apt install mariadb-client |
| erreur de compilation Python | outils de build absents | sudo apt install build-essential pkg-config libmariadb-dev |
| erreur certificat HTTPS | openssl absent |
sudo apt install openssl |