Operazioni

La documentazione ufficiale ci illustra come procedere ad interrogare le API utilizzando direttamente le librerie XMLRPC disponibili nei vari linguaggi. In questa sezione invece analizziamo come interfacciarci alla nostra applicazione tramite una libreria di più altro livello, che semplifica e ottimizza le nostre chiamate.

Login

Per effettuare qualsiasi tipo di operazione tramite API è necessario per prima cosa autenticarsi. L’autenticazione tramite API avviene utilizzando tre informazioni: username, password e nome del database dei riferimento.

Abbiamo ovviamente bisogno di conoscere anche indirizzo e porta dove gira il nostro Odoo.

Per autenticarsi apriamo una shell interattiva con

$ docker compose run odoo ipython

e al suo interno scriviamo

In [1]: import odoorpc

In [2]: odoo = odoorpc.ODOO('odoo',port=8069)

In [3]: odoo.login('demo','admin','admin')

In [4]: user = odoo.env.user

In [5]: print(user.name)
Administrator

In [6]: print(user.company_id.name)
My Company

Nel nostro caso specifico l’installazione risponde all’indirizzo odoo che abbiamo configurato nel file docker_compose.yml. Nei casi reali corrisponderà all’URL della vostra installazione

Leggere da API

Per le operazioni di lettura possiamo utilizzare diverse funzioni, disponibili anche lato backend: browse, search, search_read.

  • browser: accetta una lista di id di entità che verranno lette tutte assieme e restituisce degli oggetti rappresentanti le risorse
  • search: accetta un dominio su cui effettuare una ricerca e restituisce gli id degli oggetti trovati (è quindi poi necessario effetturare una chiamata browse per ottenerne il contenuto)
  • search_read: accetta un dominio e un elenco di attributi e restituisce dei dizionari contenenti solo i valori richiesti

Le due funzioni di ricerca accettano anche i parametri offset e limit su cui si può impostare la paginazione.

Dal momento che le richieste API viaggiano su chiamate di rete che sono notoriamenet lente, la funzione search_read acquista una notevole importanza perchè ci permette di ottimizzare i payload che dovranno poi essere scambiati fra gli endpoint, facendoci restituire solo il necessario.

Browse

Per effettuare una chiamata browse ed accedere alle risorse tramite il loro id, procediamo in questo modo

In [10]: todo = odoo.env['todo.task'].browse(3)

In [11]: todo.name
Out[11]: 'WorkShop su Odoo'

Per effettuare una chiamata browse ed accedere alle risorse tramite il loro id, procediamo in questo modo

In [12]: todos = odoo.env['todo.task'].search([('name','ilike','odoo')])

In [13]: todos
Out[13]: [3]

Search_Read

Per effettuare una chiamata browse ed accedere alle risorse tramite il loro id, procediamo in questo modo

In [15]: todos = odoo.env['todo.task'].search_read([('name','ilike','odoo')], ['id', 'name','description'])

In [16]: todos
Out[16]: 
[{'description': '<p><b>Un interessante descrizione</b><br></p>',
  'id': 3,
  'name': 'WorkShop su Odoo'}]

Creazione di record

Per creare nuovi oggetti possiamo ricorrere alla funzione create

In [15]: todo_id = odoo.env['todo.task'].create({'name': 'Test da API', 'description': 'Sono un test creato da API'})

In [16]: todo_id
Out[16]: 7

Modifica dei record

Per modificare oggetti esistenti ricorrere alla funzione write, su un oggetto resistuito da browse

In [20]: todo = odoo.env['todo.task'].browse(3)

In [21]: todo.write({'name': 'Nuovo titolo'})
Out[21]: True

Cancellazione dei record

Per cancellare oggetti esistenti ricorrere alla funzione unlink

In [27]: odoo.env['todo.task'].unlink(3)
Out[27]: True

Oppure con un approccio Active Record

In [20]: todo = odoo.env['todo.task'].browse(3)

In [21]: todo.unlink()
Out[21]: True

Altre funzioni

Ogni volta che dichiariamo un metodo con il decoratore @api.multi o @api.model quello che stiamo facendo è effettivamente dichiarare un nuovo endpoint API su quel modello. Come unica restrizione di sicurezza Odoo non permette a client diversi da il proprio client web di chiamare le funzioni che iniziano con "_".

Per esempio:

@api.model
def io_posso_essere_chiamata_da_client_esterni(self):
    return "OK"

@api.model
def _io_non_posso_essere_chiamata_da_client_esterni(self):
    return "KO"

Permette di effetturare una chiamata API come questa

In [20]: todo = odoo.env['todo.task'].browse(3)

In [21]: todo.io_posso_essere_chiamata_da_client_esterni()
Out[21]: "OK"