Capítulo IX: API Externa
Until now, we have been working with server-side code. However, the Odoo server also provides an external API, which is used by its web client and is also available for other client applications.
In this chapter, we will learn how to use the Odoo external API from our own client programs. For simplicity, we will focus on Python-based clients.
Setting up a Python client
The Odoo API can be accessed externally using two different protocols: XML-RPC and JSON-RPC. Any external program capable of implementing a client for one of these protocols will be able to interact with an Odoo server. To avoid introducing additional programming languages, we will keep using Python to explore the external API.
Until now, we have been running Python code only on the server. This time, we will use Python on the client side, so it’s possible you might need to do some additional setup on your workstation.
To follow the examples in this chapter, you will need to be able to run Python files on your work computer. The Odoo server requires Python 2, but our RPC client can be in any language, so Python 3 will be just fine. However, since some readers may be running the server on the same machine they are working on (hello Ubuntu users!), it will be simpler for everyone to follow if we stick to Python 2.
If you are using Ubuntu or a Macintosh, probably Python is already installed. Open a terminal console, type python, and you should be greeted with something like the following:
Note Windows users can find an installer and also quickly get up to speed. The official installation packages can be found at https://www.python.org/downloads/.
Calling the Odoo API using XML-RPC
The simplest method to access the server is using XML-RPC. We can use the xmlrpclib library from Python’s standard library for this. Remember that we are programming a client in order to connect to a server, so we need an Odoo server instance running to connect to. In our examples, we will assume that an Odoo server instance is running on the same machine (localhost), but you can use any IP address or server name, if the server is running on another machine.
Opening an XML-RPC connection
Let’s get a fist contact with the external API. Start a Python console and type the following:
Here, we import the xmlrpclib library and then set up some variables with the information for the server location and connection credentials. Feel free to adapt these to your specific setup.
Next, we set up access to the server’s public services (not requiring a login), exposed at the /xmlrpc/2/common endpoint. One of the methods that are available is version(), which inspects the server version. We use it to confirm that we can communicate with the server.
Another public method is authenticate(). In fact, this does not create a session, as you might be led to believe. This method just confirms that the username and password are accepted and returns the user ID that should be used in requests instead of the username, as shown here:
Reading data from the server
With XML-RPC, no session is maintained and the authentication credentials are sent with every request. This adds some overhead to the protocol, but makes it simpler to use. Next, we set up access to the server methods that need a login to be accessed. These are exposed at the /xmlrpc/2/object endpoint, as shown in the following:
Here, we are doing our first access to the server API, performing a count on the Partner records. Methods are called using the execute_kw() method that takes the following arguments: The name of the database to connect to The connection user ID The user password The target model identifier name The method to call A list of positional arguments An optional dictionary with keyword arguments
The preceding example calls the search_count method of the res.partner model with one positional argument, [], and no keyword arguments. The positional argument is a search domain; since we are providing an empty list, it counts all the Partners.
Frequent actions are search and read. When called from the RPC, the search method returns a list of IDs matching a domain. The browse method is not available from the RPC, and read should be used in its place to, given a list of record IDs, retrieve their data, as shown in the following code:
Note that for the read method, we are using one positional argument for the list of IDs, [43], and one keyword argument, fields. We can also notice that relational fields are retrieved as a pair, with the related record’s ID and display name. That’s something to keep in mind when processing the data in your code.
The search and read combination is so frequent that a search_read method is provided to perform both operations in a single step. The same result as the previous two steps can be obtained with the following:
The search_read method behaves like read, but expects as first positional argument a domain instead of a list of IDs. It’s worth mentioning that the field argument on read and search_read is not mandatory. If not provided, all fields will be retrieved.
Calling other methods
The remaining model methods are all exposed through RPC, except for those starting with “_” that are considered private. This means that we can use create, write, and unlink to modify data on the server as follows:
One limitation of the XML-RPC protocol is that it does not support None values. The implication is that methods that don’t return anything won’t be usable through XML-RPC, since they are implicitly returning None. This is why methods should always finish with at least a return True statement.
Writing a Notes desktop application Let’s do something interesting with the RPC API. What if users could manage their Odoo to-do tasks directly from their computer’s desktop? Let’s write a simple Python application to do just that, as shown in the following screenshot:
For clarity, we will split it into two files: one concerned to interact with the server backend, note_api.py, and another with the graphical user interface, note_gui.py.
Communication layer with Odoo
We will create a class to set up the connection and store its information. It should expose two methods: get() to retrieve task data and set() to create or update tasks. Select a directory to host the application files and create the note_api.py file. We can start by adding the class constructor, as follows:
Here we store in the created object all the information needed to execute calls on a model: the API reference, uid, password, database name, and the model to use. Next we will define a helper method to execute the calls. It takes advantage of the object stored data to provide a smaller function signature, as shown next:
Now we can use it to implement the higher level get() and set() methods. The get() method will accept an optional list of IDs to retrieve. If none are listed, all records will be returned, as shown here:
The set() method will have as arguments the task text to write, and an optional ID. If ID is not provided, a new record will be created. It returns the ID of the record written or created, as shown here:
if name == 'main': srv, db = 'http://localhost:8069', 'v8dev' user, pwd = 'admin', 'admin' api = NoteAPI(srv, db, user, pwd) from pprint import pprint pprint(api.get())
class NoteText(Text): def init(self, api, text='', id=None): self.master = Tk() self.id = id self.api = api Text.init(self, self.master, bg='#f9f3a9', wrap='word', undo=True) self.bind('', self.create) self.bind('', self.save) if id: self.master.title('#%d' % id) self.delete('1.0', 'end') self.insert('1.0', text) self.master.geometry('220x235') self.pack(fill='both', expand=1)
if name == 'main': srv, db = 'http://localhost:8069', 'v8dev' user, pwd = 'admin', 'admin' api = NoteAPI(srv, db, user, pwd) for note in api.get(): x = NoteText(api, note['name'], note['id']) x.master.mainloop()
$ pip install -U erppeek
import erppeek api = erppeek.Client('http://localhost:8069', 'v8dev', 'admin', 'admin') api.common.version() >>> api.count('res.partner', []) >>> api.search('res.partner', [('country_id', '=', 'be'), ('parent_id', '!=', False)]) >>> api.read('res.partner', [43], ['id', 'name', 'parent_id'])
``` As you can see, the API calls use fewer arguments and are similar to the server-side counterparts.
But ERPpeek doesn’t stop here, and also provides a representation for Models. We have the following two alternative ways to get an instance for a model, either using the model () method or accessing an attribute in camel case:
Now we can perform actions on that model as follows:
It also provides client-side object representation for records as follows:
As you can see, ERPpeek goes a long way from plain xmlrpclib, and makes it possible to write code that can be reused server side with little or no modification.
The ERPpeek CLI
Not only can erppeek be used as a Python library, it is also a CLI that can be used to perform administrative actions on the server. Where the odoo shell command provided a local interactive session on the host server, erppeek provides a remote interactive session on a client across the network.
Opening a command line, we can have a peek at the options available, as shown in the following:
Let’s see a sample session as follows:
As you can see, a connection was made to the server, and the execution context provided a reference to the model() method to get model instances and perform actions on them.
The erppeek.Client instance used for the connection is also available through the client variable. Notably, it provides an alternative to the web client to manage the following modules installed:
client.modules(): This can search and list modules available or installed
client.install(): This performs module installation
client.upgrade(): This orders modules to be upgraded
client.uninstall(): This uninstalls modules
So, ERPpeek can also provide good service as a remote administration tool for Odoo servers.
Summary
Our goal for this chapter was to learn how the external API works and what it is capable of. We started exploring it using a simple Python XML-RPC client, but the external API can be used from any programming language. In fact, the official docs provide code examples for Java, PHP, and Ruby.
There are a number of libraries to handle XML-RPC or JSON-RPC, some generic and some specific for use with Odoo. We tried not point out any libraries in particular, except for erppeek, since it is not only a proven wrapper for the Odoo/OpenERP XML-RPC but because it is also an invaluable tool for remote server management and inspection.
Until now, we used our Odoo server instances for development and tests. But to have a production grade server, there are additional security and optimization configurations that need to be done. In the next chapter, we will focus on them.
Last updated