Odoo 19 est sorti en octobre 2025, présenté lors de l'Odoo Experience à Bruxelles1. La liste des nouveautés met en avant l'IA, le studio et les vues. Une modification bien plus discrète attend pourtant les équipes techniques dans le changelog de l'ORM : le paramètre limit des champs One2many et Many2many a été retiré2. Personne n'en parle en réunion projet, et c'est précisément ce qui le rend gênant lors d'une migration.
Ce que faisait ce paramètre
Depuis longtemps, la définition d'un champ relationnel acceptait un argument limit côté Python. La documentation de l'ORM le décrivait comme une limite optionnelle appliquée à la lecture du champ3. Concrètement, un développeur écrivait quelque chose comme ceci dans son modèle :
line_ids = fields.One2many(
'sale.order.line', 'order_id',
limit=80,
)
L'idée était de plafonner le nombre d'enregistrements chargés quand on lisait le champ, pour éviter qu'un formulaire ne tire des milliers de lignes liées d'un seul coup. Beaucoup de modules métier s'appuyaient sur ce garde-fou, souvent sans que l'auteur d'origine ait laissé de commentaire pour l'expliquer.
Ce qui change en Odoo 19
Le changelog de l'ORM d'Odoo 19 acte la suppression de ce paramètre sur les deux types de champs relationnels2. Il ne fait pas partie des annonces grand public, et il s'ajoute à une série de nettoyages internes de la même version : fields_get_keys() et get_xml_id() deviennent dépréciés, _mapped_cache() disparaît, et _flush_search() est déprécié au profit d'un mécanisme porté par execute_query()2.
Le point délicat tient au comportement des champs Odoo face à un argument inconnu. Les champs acceptent des arguments arbitraires à la construction, ce qui veut dire qu'un limit=80 laissé dans une définition ne provoque pas forcément une erreur bruyante au chargement du module. Le plafond que vous croyiez actif ne l'est simplement plus, et le champ charge désormais l'ensemble des enregistrements liés. Sur une base de démonstration avec dix lignes, rien ne se voit. Sur une base de production avec des commandes qui comptent plusieurs milliers de lignes, la lecture du formulaire ralentit sans message clair. Vérifiez donc le comportement réel sur un environnement de recette avant de conclure quoi que ce soit.
Le piège du double sens de « limit »
Une confusion revient souvent, et elle mérite d'être posée à plat. Il existe deux endroits différents où le mot limit apparaît dans Odoo, et seul l'un des deux est concerné.
| Emplacement | Rôle | Statut en Odoo 19 |
|---|---|---|
Argument Python sur fields.One2many / fields.Many2many | Limite à la lecture du champ | Retiré2 |
Attribut sur la vue liste (<list limit="80">) | Pagination de l'affichage | Toujours valide |
L'attribut de vue continue de fonctionner et reste la façon recommandée de contrôler combien de lignes s'affichent dans un formulaire4. Si votre besoin était surtout visuel, la migration consiste à déplacer l'intention du modèle vers la vue, ce qui est de toute façon un meilleur emplacement pour une règle d'affichage.
Comment auditer vos modules
Un audit rapide se fait à la main. Recherchez les occurrences de limit= dans les définitions de champs de vos addons custom, en écartant les search() et read_group() qui utilisent aussi ce mot pour un usage légitime et inchangé. Une commande de type grep -rn "limit=" --include="*.py" sur votre dépôt de modules donne la liste des points à examiner un par un.
Pour chaque occurrence trouvée sur un champ relationnel, posez-vous la question du besoin d'origine. S'il s'agissait de brider l'affichage, l'attribut de vue reprend le relais. S'il s'agissait de protéger les performances de lecture, il faut réfléchir à la structure elle-même.
Les schémas qui tiennent dans la durée
Quand une relation peut compter des milliers d'enregistrements, la plafonner à la lecture n'a jamais été qu'un pansement. Un domaine bien posé sur le champ filtre les enregistrements pertinents au lieu d'en couper arbitrairement une partie. Pour les volumes vraiment importants, une vue dédiée avec sa propre pagination, ouverte à la demande, garde le formulaire principal léger. Ces approches survivent aux montées de version parce qu'elles reposent sur des mécanismes stables plutôt que sur un argument de commodité.
Cette suppression rejoint la logique générale des changements ORM d'Odoo 19 : l'éditeur retire les raccourcis peu utilisés et pousse vers des constructions explicites.
Notre lecture
Ce changement ne casse pas un module au démarrage, et c'est justement pour cela qu'il faut le traiter tôt. Un plafond silencieusement désactivé se transforme en lenteur inexpliquée trois semaines après la mise en production, au moment où le lien avec la migration n'est plus évident pour personne. Dans nos audits de code avant montée de version, la recherche de limit= sur les champs relationnels fait désormais partie de la liste de contrôle systématique. Le coût de l'audit se mesure en minutes, celui d'un formulaire qui se met à ramer en production se mesure en tickets de support.
Sources
- Odoo (Wikipedia), historique des versions et sortie d'Odoo 19 : https://en.wikipedia.org/wiki/Odoo
- Changelog ORM Odoo 19.0 (documentation officielle) : https://www.odoo.com/documentation/19.0/developer/reference/backend/orm/changelog.html
- ORM API Odoo 17.0, description du paramètre limit sur One2many : https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html
- One2many Tree/List View Limit, module de vue (Odoo Apps Store 19.0) : https://apps.odoo.com/apps/modules/19.0/one2many_tree_view_limit
Footnotes
-
Odoo 19 a été publié en octobre 2025 dans la foulée de l'Odoo Experience tenue à Bruxelles. ↩
-
Le changelog de l'ORM d'Odoo 19.0 documente la suppression du paramètre
limitsurOne2manyetMany2many, ainsi que la dépréciation defields_get_keys(),get_xml_id(),_flush_search()et le retrait de_mapped_cache(). ↩ ↩2 ↩3 ↩4 -
La documentation de l'ORM des versions antérieures décrit
limitcomme une limite optionnelle appliquée lors de la lecture du champ relationnel. ↩ -
L'attribut
limitsur la vue liste reste un mécanisme distinct, dédié à la pagination de l'affichage, et n'est pas concerné par cette suppression. ↩