Conect to Odoo database

Here we connect to odoo database via XML RPC protocol. For all possible arguments of Client class look at documentation

In [1]:
# Import Client and Session classes
from openerp_proxy import (Client,
                           Session)

cl = Client('localhost', 'openerp_proxy_test_db', 'admin', 'admin', protocol='xml-rpc')

Also it is posible to use JSON-RPC protocol, and HTTPS versions of both XML-RPC and JSON-RPC. Note that connection via HTTPS is not well tested, but if there are some errors, while connection, just fill an issue on github project page.

To list all available connectors, use openerp_proxy.connection.get_connector_names() which returns a list with registered connector names.

By default they are:

  • xml-rpc
  • xml-rpcs
  • json-rpc
  • json-rpcs.
In [2]:
from openerp_proxy.connection import get_connector_names
get_connector_names()
Out[2]:
['json-rpc', 'xml-rpc', 'xml-rpcs', 'json-rpcs']

But new connectors could be easily added via extension mechanism. For examples look at source code of openerp_proxy.connection package.

Client usage

Client instance is a start point of any usage of this project. For low level code, it provides execute method which allows to execute any public method on any model of connected Odoo instance and execute_wkf method, which sends signal to workflow engine:

So simple search-read code should look like:

In [3]:
partner_ids = cl.execute('res.partner', 'search', [('parent_id', '!=', False)], limit=3)
partner_data = cl.execute('res.partner', 'read', partner_ids, ['id', 'name', 'country_id'])
partner_data
Out[3]:
[{'country_id': [21, 'Belgium'], 'id': 31, 'name': 'Michel Fletcher'},
 {'country_id': [21, 'Belgium'], 'id': 30, 'name': 'Thomas Passot'},
 {'country_id': [229, 'Taiwan'], 'id': 29, 'name': 'Joseph Walters'}]

ORM functionality

But to simplify code of data processing there are ORM layer, which usualy accesed from Client instances.

Few notes about terminology:

  • Term 'object' here and in documentation mostly refers to Odoo's Model (Document type)
  • Term 'record' here and in documentation mostly refers to single Odoo's document (database record)

Next code demonstrate's client.get_obj(), object.search() and object.read() methods. at first we get partner object, then search for partners that have parent partners, and finaly we read 3 fields for each partner searched.

search and read are standard Odoo methods, and all arguments will be passed directly to server

In [4]:
partner_obj = cl.get_obj('res.partner')
partner_ids = partner_obj.search([('parent_id', '!=', False)], limit=3)
partner_data = partner_obj.read(partner_ids, ['id', 'name', 'country_id'])
partner_data
Out[4]:
[{'country_id': [21, 'Belgium'], 'id': 31, 'name': 'Michel Fletcher'},
 {'country_id': [21, 'Belgium'], 'id': 30, 'name': 'Thomas Passot'},
 {'country_id': [229, 'Taiwan'], 'id': 29, 'name': 'Joseph Walters'}]

This code looks much simpler! But if dealing with relational fields, is still not so comfortable as desired. For example, we want to get list of country codes, of partners selected. Our code will be something similar to:

In [5]:
country_ids = [p['country_id'][0] for p in partner_data]
country_data = cl['res.country'].read(country_ids, ['code'])
country_codes = [c['code'] for c in country_data]
country_codes
Out[5]:
['BE', 'TW']

But there are simpler way to do this, using special methods search_records and read_records, that wraps data been read in RecordList or Record classes.

Note that, while search_records method usualy returns RecordList instance, read_records will return single Record instance if single id is passed to it instead of list of ids.

In [6]:
partner_obj = cl['res.partner']
partners = partner_obj.search_records([('parent_id','!=', False)], limit=3)
country_codes = [p.country_id.code for p in partners]

# and to remove dublicates
country_codes = list(set(country_codes))
country_codes
Out[6]:
['BE', 'TW']

Also there is RecordList.mapped method, that could help a lot. It mostly same as serverside RecordSet.mapped method, but does not support function as parametr yet. Code which uses it may look like:

In [7]:
partner_obj = cl['res.partner']
partners = partner_obj.search_records([('parent_id','!=', False)], limit=3)
country_codes = partners.mapped('country_id.code')
country_codes
Out[7]:
['BE', 'TW']