Relazioni

Abbiamo visto come lavoare con tipi di campi non relazionali, ma nelle applicazioni reali una buona parte delle strutture dati descrivono relazioni fra le entità. L’ORM di Odoo è in grado di gestire i vari tipi di relazioni fra oggetti, mettendo a disposizione un set di funzionalità pronte all’uso.

Per avere chiaro cosa stiamo per fare, chiariamo cosa vogliamo costruire. Finora abbiamo lavorato con l’oggetto TodoTask. Adesso aggiungeremo il modello TodoProject che raggruppa i Task, e il modello TodoTag che li classifica. Ogni TodoTask può appartenere a un solo progetto, c’è quindi una relazione N a 1 fra di loro. Stessi tag possono invece essere assegnati a diversi TodoTask, avranno quindi una relazione N a N tra di loro.

Realazioni Many2one

Nel caso della relazione fra progetti e task abbiamo detto che esiste una relazione Molti a uno (o Uno a molti guardandola dall’altra parte). Per aggiungere questo tipo di relazione in odoo possiamo ricorrere al tipo di campo Many2one.

Apriamo quindi il file models/task_task.py contenente il nostro modello TodoTask e aggiungiamo questo campo alla classe:

project_id = fields.Many2one('todo.project', string='Project')

Successivamente apriamo il nostro views/task_task.xml e aggiungiamolo anche alla vista form:

<field name='name' position='after'>
    <field name='project_id'/>
</field>

Realazioni One2many

Considerando invece la relazione dal punto di vista opposto, quello dei progetti, la relazione è inversa: ogni TodoProject sarà legato a tanti oggetti TodoTask. Questo tipo di relazione in Odoo è chiamata One2many. Per definirla è necessario definire nella dichiarazione del campo su quale attributo dell’oggetto figlio avviene la relazione. Uno stesso oggetto potrebbe avere più relazioni One2many verso la stessa classe di oggetti.

Per aggiunger questa relazione al nostro modello dei progetti aprima il file models/task_project.py e aggiungiamo nel corpo della classe:

    todo_ids = fields.One2many('todo.task', 'project_id', string='Todos')

Per convenzione su Odoo i nomi dei campi relazionali vengono sempre terminati con _id o _ids. Questo per indicare velocemente agli sviluppatori se si tratta di una relazione a uno oppure a molti. Consiglio vivamente di continuare con questa convenzione.

E nel file delle viste dei progetti views/task_project.xml aggiungiamo questo record:

<record model="ir.ui.view" id="todo_project_form_view">
    <field name="name">todo.project.form</field>
    <field name="model">todo.project</field>
    <field name="arch" type="xml">
        <form string="ToDo Project Form">
            <header>
                <field name='state' widget='statusbar'/>
            </header>
            <sheet>
                <group name="group_top">
                    <group name="group_left">
                        <field name="name"/>
                    </group>
                </group>

                <field name='todo_ids'/>
            </sheet>
        </form>
    </field>
</record>

Aggiorniamo il modulo

    $ docker compose run odoo upgrade todo_plus

e ricarichiamo la pagina

todo_ids

Questa volta Odoo ci renderizza il campo come una lista di oggetti Todo, entrando in modalità modifica vediamo che è possibile aggiungere righe cercandole da quelle esistenti oppure crearne di nuove tramite la Form View specifica degli oggeti TodoTask.

Realazioni Many2many

Le relazioni Many2Many sono molto simili alle One2Many, nel senso che ad un oggetto ne vengono legati molti e sono quindi spesso rappresentato con lo stesso widget delle One2Many. La grossa differenza però è a livello di database.

One2many: gli oggetti sono correlati da un id presente in una colonna della tabella figlia, nel nostro caso la colonna project_id della tabella dei todo Many2many: viene creata una terza tabella composta da due colonne che fanno riferimento agli id delle due entità in relazione.

Nel nostro esempio vogliammo aggiungere una relazione fra il modello TodoTag e il modello TodoTask. Per farlo apriamo prima il file del modello models/task_task.py e aggiungiamo il campo:

tag_ids = fields.Many2many('todo.tag', string='Tag')

Successivamente apriamo il nostro views/task_task.xml e aggiungiamolo anche alla vista form:

<!-- All'interno del campo arch aggiungiamo  -->
<field name='user_id' position='after'>
    <field name='tag_ids'/>
</field>

Aggiorniamo il modulo

$ docker compose run odoo upgrade todo_plus

e ricarichiamo la pagina

tags1

Il campo Tag è stato aggiunto e visualizzato come una lista di oggetti.

Una finezza

Odoo ha diversi widget che possono essere utilizzati per renderizzare i campi agli utenti (e anche loro possono essere aggiunti o modificati). Nel caso specifico Odoo ha un widget per gestire i tag. Per utilizzarlo bisogna modificare la dichiarazione nella vista form aggiungendo widget=“many2many_tags” tra gli attributi del campo tag_ids, come segue

<field name='user_id' position='after'>
    <field name='tag_ids' widget="many2many_tags"/>
</field>

Aggiornando la pagina otteniamo una visualizzazione del campo molto più comoda ed inerente allo stesso

tags2

Continua

Ora che abbiamo creato le nostre prima relazioni possiamo occuparci di un altro strumento molto utile che Odoo ci fornisce sui modelli, i computed fields