Here we connect to odoo database via XML RPC protocol. For all possible arguments of Client class look at documentation
# 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:
from openerp_proxy.connection import get_connector_names
get_connector_names()
['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 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:
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
[{'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'}]
But to simplify code of data processing there are ORM layer, which usualy accesed from Client instances.
Few notes about terminology:
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
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
[{'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:
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
['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.
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
['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:
partner_obj = cl['res.partner']
partners = partner_obj.search_records([('parent_id','!=', False)], limit=3)
country_codes = partners.mapped('country_id.code')
country_codes
['BE', 'TW']