1. Remplacez le modèle de page par la version finale
Le contrôleur fournit modules. Le template, c’est-à-dire le modèle de page QWeb, parcourt cette collection et n’affiche que deux fields (champs techniques) de chaque formation fictive : name et description.
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="formations_page" name="Liste locale des formations">
<t t-call="website.layout">
<div id="wrap" class="oe_structure">
<main class="container py-5">
<nav aria-label="Navigation des formations" class="mb-4">
<a href="/formations">Toutes les formations</a>
</nav>
<header class="mb-4">
<p class="text-muted">Sélection locale</p>
<h1>Formations disponibles</h1>
<p>Ces formations fictives servent uniquement à l’exercice.</p>
</header>
<section aria-labelledby="selection-title">
<h2 id="selection-title" class="h3">Choisissez une formation</h2>
<p t-if="not modules" class="alert alert-info" role="status">
Aucune formation d’exercice n’est disponible.
</p>
<div t-if="modules" class="row g-3">
<div class="col-12 col-md-6"
t-foreach="modules" t-as="module">
<article class="h-100 p-3 border rounded">
<h3 class="h5">
<t t-out="module.name"/>
</h3>
<p t-if="module.description">
<t t-out="module.description"/>
</p>
<a class="btn btn-outline-primary mt-3"
t-att-href="'/odoo/action-elearning_portal.elearning_module_action/%s' % module.id">
Ouvrir la fiche interne
</a>
</article>
</div>
</div>
</section>
</main>
</div>
</t>
</template>
</odoo>t-out échappe les textes avant de les insérer dans le HTML. Les classes utilisées viennent de Bootstrap, déjà fourni par Website ; aucun service externe n’est chargé.
À observer : le code ne contient ni note_ids, ni training.note, ni titre ou contenu de note. Le seul identifiant d’enregistrement Odoo utilisé sert à construire le lien vers la fiche interne.
2. Déclarez Website, le module de site d’Odoo, au moment où il est utilisé
Le modèle de page appelle désormais website.layout et le contrôleur utilise website=True. Ajoutez donc les dépendances et le chemin du modèle de page. Voici le manifeste complet tel qu’il doit se présenter à la fin du laboratoire.
{
"name": "Portail de formations",
"summary": "Relier des formations aux notes du module de formation",
"version": "19.0.1.0.0",
"category": "Training",
"author": "Formation Odoo",
"license": "LGPL-3",
"depends": [
"training_hello",
"website",
],
"data": [
"security/ir.model.access.csv",
"data/elearning_module_data.xml",
"views/elearning_module_views.xml",
"views/templates.xml",
],
"application": True,
"installable": True,
}training_hello fournit training.note et ses external IDs (identifiants externes). website fournit le routeur Website, website.layout et les composants visuels employés ici. Ces deux dépendances sont chargées avant elearning_portal.
Résultat attendu après la mise à niveau : Odoo charge le modèle de page elearning_portal.formations_page. L’ajout de website aux dépendances ne rend aucune donnée publique ; la route conserve auth="user".
3. Rechargez chaque couche dans le bon ordre
- Enregistrez le contrôleur, les deux
__init__.py, le modèle de page et le manifeste. - Redémarrez Odoo pour charger le code Python et enregistrer la route.
- Dans Applications, mettez Portail de formations à niveau. Cette action modifie la base d’exercice : elle charge les dépendances et le XML déclaré.
- Connectez-vous avec un utilisateur interne couvert par l’ACL
base.group_user. - Ouvrez
/formationssur votre serveur Odoo local.
Résultat attendu : la page Website affiche le titre Formations disponibles ainsi que deux cartes triées par nom. Chaque carte contient le nom, la description fictive et le bouton Ouvrir la fiche interne.
4. Réalisez le test visuel
- Sélection : recherchez les titres Bases du développement Odoo et Pratiquer dans une base d’exercice.
- Absence des notes : vérifiez que Bienvenue, Observer avant de modifier, Une base d’exercice et leurs contenus ne s’affichent pas comme des notes sur la page.
- Fiche réelle : cliquez sur le bouton de la première carte. Le client web ouvre la vue de formulaire du même enregistrement
elearning.moduleà une URL de la forme/odoo/action-elearning_portal.elearning_module_action/…. - Relation interne : dans cette fiche de l’interface interne, retrouvez les notes associées. Elles sont visibles parce que vous êtes dans l’interface interne et que votre session possède les droits nécessaires.
- Clavier : revenez à
/formations, puis utilisez Tab et Entrée. Le lien de chaque carte doit être atteignable sans souris. - Téléphone : testez la page sur un écran d’environ 360 px de large. Les cartes doivent se placer sur une seule colonne sans débordement horizontal.
Website n’affiche que le nom et la description. L’interface interne présente en plus la relation vers les notes. Le model (modèle de données Odoo), l’ORM, PostgreSQL et les droits restent les mêmes ; seuls les champs affichés et la présentation changent.
5. Corrigez la première cause, pas le dernier symptôme
custom_addons/elearning_portal/controllers/__init__.py— si/formationsrenvoie une 404, vérifiez l’import : la valeur attendue estfrom . import main.custom_addons/elearning_portal/__init__.py— si la route reste absente, vérifiez le package Python (le dossier importable) : la valeur attendue contientfrom . import controllers.custom_addons/elearning_portal/__manifest__.py— si QWeb ne trouve pas le modèle de page, vérifiezdata: la valeur attendue contientviews/templates.xml.custom_addons/elearning_portal/views/templates.xml— si le rendu échoue, vérifiez l’ID : la valeur attendue estformations_page.custom_addons/elearning_portal/security/ir.model.access.csv— si la recherche ou la fiche est refusée, vérifiez le groupe etperm_read: les valeurs attendues sontbase.group_useret1.custom_addons/elearning_portal/views/templates.xml— si des notes apparaissent sur Website, vérifiez les expressions QWeb : aucune expression attendue ne contientnote_ids.
Redémarrez après toute correction de Python. Mettez le module à niveau après une correction du manifeste ou du XML. Rechargez ensuite la page ; ce dernier geste ne remplace jamais les deux précédents.
La page locale n’affiche que les formations autorisées. Le bouton ouvre leur véritable fiche dans l’interface interne avec l’URL actuelle d’Odoo 19, et aucune étape ne contourne la session ou les ACL.