Introduzione
Il campo Many2One è uno dei mattoni fondamentali del modello dati di Odoo. Ogni volta che colleghi un ordine di vendita a un cliente, assegni un prodotto a una categoria o associ un’attività a un progetto, stai usando questa relazione. Per chi lavora su personalizzazioni o sviluppo in Odoo, saperlo gestire correttamente significa costruire sistemi coerenti e navigabili.
Dal punto di vista aziendale, i Many2One permettono a Odoo di funzionare come un unico ecosistema: senza di loro i moduli resterebbero compartimenti stagni. Grazie a questi collegamenti, le informazioni scorrono tra documenti diversi e gli utenti possono spostarsi fra record correlati senza pensare alla struttura del database.
Questa guida spiega cosa memorizza un Many2One, come si comporta nell’ORM e nell’interfaccia, come crearne uno con Odoo Studio o in Python, e mostra esempi pratici tratti da CRM, Vendite, Magazzino e Contabilità.
Che cos’è il campo Many2One in Odoo
Nel linguaggio dell’ORM di Odoo, un campo Many2One è un puntatore da un record verso uno e un solo record di un altro modello. Il nome descrive la relazione dal punto di vista del modello corrente: molte righe qui possono riferirsi a una sola riga là. È il modo più semplice e frequente per rappresentare relazioni tipo molti-uno.
A livello di database, un Many2One si traduce in una chiave esterna nella tabella corrente. Se un ordine di vendita punta al cliente con ID 42, nella colonna corrispondente della tabella ordine viene salvato il valore intero 42. Odoo poi risolve automaticamente il join e recupera il nome del record collegato per mostrarlo all’utente.
Nell’interfaccia utente il Many2One si presenta tipicamente come un campo con completamento automatico o un menu a discesa: si digita qualche carattere e Odoo filtra i record corrispondenti. Quando si seleziona un elemento, il collegamento è stabilito. L’utente vede il nome del record collegato, non l’ID interno, il che rende l’esperienza immediata e leggibile.
Ecco un esempio di definizione in Python:
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_account_manager_id = fields.Many2One(
comodel_name='res.users',
string='Account Manager',
ondelete='set null',
)
Il parametro comodel_name indica il nome tecnico del modello di destinazione. ondelete definisce cosa accade ai record correnti se il record collegato viene cancellato: cascade elimina anche i riferimenti, set null azzera il collegamento e restrict impedisce l’eliminazione finché esistono riferimenti.
In Odoo Studio il campo Many2One è disponibile nella scelta dei campi come Many2One. Aggiungendolo con Studio si seleziona il modello target da una lista e lo strumento crea automaticamente il campo: è il modo più immediato per introdurre relazioni senza scrivere codice.
Come funziona il campo
Se leggi un Many2One dall’ORM, ottieni un recordset che rappresenta il record collegato; se il campo è vuoto ottieni un recordset vuoto. In Python puoi accedere direttamente ai campi del record collegato usando la notazione a punti per leggere nome, indirizzo, o altri attributi.
order = self.env['sale.order'].browse(1)
customer_name = order.partner_id.name
customer_city = order.partner_id.city
Questa navigazione a catena è uno dei punti di forza dell’ORM: non devi scrivere join espliciti o query SQL; l’ORM si occupa di recuperare i dati correlati in background.
Quando usi l’API XML-RPC, un Many2One viene restituito come una lista a due elementi: l’ID intero e la stringa del display name, ad esempio [42, "Acme Corp"]. Se il campo è vuoto l’API restituisce False. È un dettaglio importante per chi elabora risposte remote in script o integrazioni.
Attributi chiave del campo
Queste sono le proprietà più rilevanti che puoi impostare su un campo Many2One in Odoo:
- comodel_name: il nome tecnico del modello di destinazione. È l’unico parametro obbligatorio.
- ondelete: definisce il comportamento quando il record collegato viene cancellato. Le opzioni sono
'cascade','set null'e'restrict'. Il valore predefinito è spesso'set null'. - domain: un filtro che limita i record selezionabili nel menu; ad esempio
domain=[('customer_rank', '>', 0)]limita la scelta ai soli clienti. - context: parametri aggiuntivi passati quando si apre il record collegato o il dropdown; utili per precompilare campi al momento della creazione di un record correlato.
- required: rende il campo obbligatorio: il record non può essere salvato senza un valore.
- readonly: impedisce modifiche manuali al collegamento; utile quando il valore è impostato via codice e non deve essere cambiato dagli utenti.
- delegate: se attivato rende i campi del modello collegato direttamente accessibili nel modello corrente; questa opzione è tipica dell’ereditarietà di modello in Odoo e non va confusa con le normali relazioni Many2One.
Come appare nelle viste
Nel form il Many2One viene mostrato con una casella di ricerca o un dropdown con typeahead: l’utente digita parte del nome per filtrare. Un’icona accanto al campo permette di aprire direttamente il record collegato, agevolando la navigazione senza passare dai menu principali.
Nelle liste il campo mostra il nome del record collegato e può essere usato per raggruppare i dati: ad esempio raggruppare ordini di vendita per cliente o attività per progetto, utile in reportistica e panoramiche operative.
Nelle ricerche il Many2One è sfruttato come filtro o criterio di raggruppamento: cercare opportunità per cliente significa filtrare su un campo Many2One.
Il reciproco One2Many
Ogni Many2One ha naturalmente un lato inverso: il One2Many. Se gli ordini puntano al cliente con un Many2One, dal record cliente puoi mostrare l’elenco degli ordini correlati tramite un One2Many. È buona pratica definire entrambe le facce della relazione: migliora la navigazione e la fruibilità. Il One2Many non crea una colonna aggiuntiva nel DB, ma si calcola a partire dalla chiave esterna presente sul lato opposto.
Casi d’uso aziendali
Il campo Many2One è onnipresente in Odoo e vale la pena vedere esempi concreti tratti dai processi aziendali più comuni.
CRM: collegare lead a venditori
Nel modulo CRM ogni lead/opportunità ha un campo user_id Many2One verso res.users: è il commerciale responsabile. Grazie a questo campo i manager possono filtrare la pipeline per agente, analizzare tassi di conversione e assegnare lead in massa. Se servono ruoli aggiuntivi (es. account manager secondario) si aggiunge semplicemente un altro Many2One verso lo stesso modello.
Vendite: collegare ordini a clienti e listini
Un ordine di vendita tipico contiene almeno due Many2One importanti: partner_id per il cliente e pricelist_id per il listino. Scegliendo il cliente, Odoo può compilare automaticamente listino, termini di pagamento e indirizzo di consegna usando metodi onchange che leggono il Many2One e riempiono gli altri campi: è uno dei vantaggi pratici di un modello dati ben strutturato.
Magazzino: prodotti e categorie
Ogni prodotto appartiene a una categoria tramite un Many2One (categ_id su product.template). La categoria influisce su contabilità dei costi, metodo di valutazione e strategie di prelievo. Assegnare correttamente la categoria è cruciale per i report finanziari; il Many2One rende questa assegnazione semplice e riutilizzabile su centinaia di prodotti.
Contabilità: scritture e registri
Ogni movimento contabile è collegato a un giornale tramite un Many2One (journal_id su account.move). Il giornale definisce la numerazione, il tipo di operazione e talvolta i conti di default. Scegliere il giornale sbagliato su una fattura o un pagamento può posizionare le scritture nel posto sbagliato nel libro mastro; il Many2One qui non è solo comodità, ma controllo di accuratezza contabile.
Project management: attività e progetti
Nel modulo Project ogni attività appartiene a un progetto tramite il Many2One project_id. Questo collegamento determina flussi di stage, chi può accedere all’attività e come vengono allocate le schede orarie. Per aziende che fatturano a progetto, il legame Many2One tra timesheet, task e progetto è essenziale per riconoscimento ricavi e fatturazione.
Creare o personalizzare un campo Many2One
Tre modi per aggiungere un Many2One a un modello Odoo, a seconda del livello tecnico e del contesto di deployment.
Con Odoo Studio (no-code)
Odoo Studio è lo strumento low-code integrato. Per aggiungere un Many2One senza programmare:
- Apri Odoo Studio dal menu principale.
- Vai al form dove vuoi inserire il campo.
- Trascina un campo Many2One dalla palette sul form.
- Nelle proprietà seleziona il modello di destinazione dalla lista.
- Imposta l’etichetta e, se serve, un filtro di dominio per limitare le scelte.
- Salva e chiudi Studio.
Studio crea il campo con prefisso x_studio_ e lo aggiunge automaticamente alla vista. Il campo è subito operativo: gli utenti possono cercare e selezionare record collegati. È il modo più rapido per estendere un form quando non si vuole intervenire sul codice sorgente.
Con Python in un modulo personalizzato
Per sviluppatori che gestiscono moduli, i Many2One si dichiarano in Python. È la strada suggerita per sviluppi che devono essere versionati e distribuiti in ambienti diversi:
from odoo import fields, models
class ProjectTask(models.Model):
_inherit = 'project.task'
x_client_contact_id = fields.Many2One(
comodel_name='res.partner',
string='Client Contact',
domain=[('type', '=', 'contact')],
ondelete='set null',
help='The main contact at the client for this task.',
)
Dopo aver definito il campo nel modello, va aggiunto alla vista XML corrispondente e va eseguito un aggiornamento del modulo per applicare le modifiche al database. Questo metodo offre controllo totale su domain, ondelete, compute e vincoli ed è l’approccio standard per campi relazionali in produzione.
Quando crei un Many2One in una personalizzazione, è buona pratica aggiungere anche il corrispondente One2Many sul modello collegato per consentire la navigazione a doppio senso.
class ResPartner(models.Model):
_inherit = 'res.partner'
x_task_ids = fields.One2Many(
comodel_name='project.task',
inverse_name='x_client_contact_id',
string='Related Tasks',
)
Con l’API XML-RPC
Se gestisci personalizzazioni tramite script o configurazioni remote, puoi creare campi Many2One anche via XML-RPC:
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_client_segment_id',
'field_description': 'Client Segment',
'model_id': model_id,
'ttype': 'many2one',
'relation': 'res.partner.category',
'on_delete': 'set null',
'state': 'manual',
}]
)
La chiave relation indica il modello di destinazione e on_delete definisce il comportamento alla cancellazione. Quando crei un campo via API, ricorda sempre di aggiungere anche l’One2Many inverso così la navigazione funzioni da entrambi i lati: è una regola pratica per configurazioni remote ben gestite.
Buone pratiche
1. Crea sempre l’One2Many inverso
Quando aggiungi un Many2One, definisci anche il corrispondente One2Many sul modello collegato. Non crea colonne addizionali nel database ma migliora moltissimo l’esperienza utente: dal form del cliente l’utente potrà vedere subito tutte le righe che lo collegano, evitando ricerche manuali.
2. Usa filtri domain per limitare le scelte
Un Many2One verso res.partner di default mostra tutti i partner (fornitori, clienti, contatti interni, indirizzi di consegna). Se il campo è destinato ai soli clienti, applica un domain come domain=[('customer_rank', '>', 0)] per ridurre il rumore e prevenire selezioni errate che porterebbero a problemi a valle.
3. Scegli con attenzione ondelete
Il comportamento ondelete è più importante di quanto sembri: 'cascade' cancella i record dipendenti se il master viene rimosso, con rischio di perdite massicce. Nella maggior parte dei casi 'set null' è la scelta più sicura; usa 'restrict' quando il master non deve essere eliminato se esistono riferimenti.
4. Non duplicare dati che dovrebbero essere relazioni
Un errore comune è creare campi di testo per memorizzare nomi o categorie già disponibili in un altro modello. Questo porta a duplicazione, filtri meno precisi e incoerenze quando i nomi cambiano. Se i valori esistono altrove, usa una relazione Many2One invece di una stringa libera.
5. Usa il context per precompilare record correlati
L’attributo context permette di passare valori predefiniti quando l’utente crea un record collegato dal dropdown. Ad esempio puoi preimpostare il progetto su un nuovo contatto legato a quel progetto, riducendo inserimenti manuali e mantenendo la coerenza dei dati.
Trappole comuni
Dimenticare l’One2Many inverso
Il problema più frequente è aggiungere solo il Many2One senza l’inverso: si crea un collegamento unidirezionale e dal record collegato non si vede chi lo punta. Gli utenti finiscono per lamentarsi di non poter trovare facilmente i record correlati e qualcuno costruisce ricerche o report ad hoc per compensare l’assenza dell’One2Many.
Usare cascade senza riflettere
Impostare ondelete='cascade' su molti record operativi collegati a un master può provocare perdite di dati disastrose. Se elimini una categoria prodotto e tutti i prodotti collegati vengono cancellati per effetto cascade, il danno è notevole. Nella maggior parte dei casi è preferibile set null o restrict per proteggere i dati di business.
Non controllare il valore False quando navighi in Python
Se un Many2One è vuoto, in Python restituisce un recordset vuoto (falsy). Accedere direttamente a catene come order.partner_id.country_id.name senza verifiche può produrre stringhe vuote silenziose quando un link intermedio è mancante, causando output errati in report o email. Controlla sempre l’esistenza del record quando il campo non è obbligatorio.
Puntare al modello sbagliato
Il modello res.partner in Odoo rappresenta clienti, fornitori, contatti e società. Un Many2One verso res.partner senza domain consente di scegliere qualsiasi tipo di partner. Se il campo è destinato ai soli clienti, imposta il domain appropriato: altrimenti gli utenti vedranno indirizzi di consegna o utenti interni e potranno selezionare valori non coerenti con il processo.
Abusare dei Many2One quando basta una Selection
Se l’insieme dei valori è fisso e limitato, una Selection è più semplice ed efficiente di un Many2One: non serve un modello separato né un join sul DB. Per uno stato con tre o quattro opzioni, preferisci una Selection; usa Many2One quando i valori sono numerosi, gestiti dinamicamente o condivisi tra più moduli.
Conclusione
Il Many2One è il cuore del collegamento dei dati tra i moduli in Odoo. Capirne il funzionamento non è solo prerogativa degli sviluppatori: analisti funzionali, consulenti e power user che usano Studio ne traggono grande vantaggio per estendere la piattaforma in modo solido.
Punti chiave da ricordare: definisci sempre l’One2Many inverso per una navigazione completa, usa domain per mantenere i dropdown puliti e pertinenti, scegli attentamente il comportamento ondelete e non usare Many2One quando una Selection è più appropriata.
Che tu stia configurando un campo con Odoo Studio, sviluppando un modulo Python o gestendo il modello dati via XML-RPC, impostare correttamente le relazioni fin dall’inizio rende l’implementazione più affidabile e più semplice da mantenere nel tempo.
Da Dasolo offriamo supporto per implementare, personalizzare e ottimizzare Odoo in tutta l’azienda. Se ti serve aiuto per progettare un modello dati chiaro, aggiungere relazioni ai form o sviluppare un modulo completo, il nostro team è a disposizione. Contattaci e parliamo del tuo progetto Odoo.