External API - Integrating with Other Systems Overview Overview The PerfectWORK server provides an external API, which is used by its web client and is available for other client applications. In this chapter, we'll learn how to use the PerfectWORK external API from our own client programs, using PerfectWORK's external API. To avoid introducing additional languages the reader might not be familiar with, here we will focus on Python-based clients, although the techniques to handle the RPC calls also applies to other programming languages. We'll describe how to use the PerfectWORK RPC calls, and then use that knowledge to build a simple Library command-line application using Python. Setting up Python on the client machine 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'll need to be able to run Python files on your work computer. We will be using Python 3 for this. At this point, you should make sure you have Python 3 installed in your workstation. This can be confirmed running the python3 --version command in a Terminal. If not, you may refer the official website for your platform's installation package, at https://www.python.org/downloads/. For Ubuntu, at this point, you probably already have Python 3 installed. If not, you can install it by running the following: $ sudo apt-get install python3 python3-pip If you are a Windows user and have Odoo installed on your machine, you may be wondering why you don't already have a Python interpreter and why additional installation is needed. The short answer is that the Odoo installation has an embedded Python interpreter that isn't easily used outside. Connecting to 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 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 reachable IP address or server name, if the server is running on a different machine. Let's make first contact with the Odoo external API. Start a Python 3 console and type in the following: >>> from xmlrpc import client >>> srv = 'http://localhost:8069' >>> common = client.ServerProxy('%s/xmlrpc/2/common' % srv) >>> common.version(){'server_version': '12.0', 'server_version_info': [12, 0, 0, 'final', 0,''], 'server_serie': '12.0', 'protocol_version': 1} Here, we import the xmlrpc.client library and then set up a variable with the information for the server address and listening port. 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's 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 doesn't 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: >>> db = '12-library' >>> user, pwd = 'admin', 'admin' >>> uid = common.authenticate(db, user, pwd, {})>>> print(uid) 2 We start by setting, in the db variable, the database name we will use. In our example, it's 12- library, but you are free to change it if you are working with a database with a different name. If the login credentials are not correct, a False value is returned, instead of a user ID. The authenticate() last argument is the user agent environment, used to provide the server with some metadata about the client. It's mandatory, but can be an empty dictionary. Running server methods using XML-RPC 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: >>> api = client.ServerProxy('%s/xmlrpc/2/object' % srv) >>> api.execute_kw(db, uid, pwd, 'res.partner', 'search_count', [[]]) 42 Here, we are accessing the server API for the first time, 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 (not used in the example) 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 of 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 obtain a list of record IDs and retrieve their data, as shown in the followingcode: >>> domain = [('is_company', '=', True)] >>> api.execute_kw(db, uid, pwd, 'res.partner', 'search', [domain])[14, 10, 11, 15, 12, 13, 9, 1] >>> api.execute_kw(db, uid, pwd, 'res.partner', 'read', [[14]], {'fields':['id', 'name', 'country_id']})[ {'id': 14, 'name': 'Azure Interior', 'country_id': [233, 'UnitedStates']}] Note that, for the read method, we're using one positional argument for the list of IDs, [14], and one keyword argument, fields. We can also notice that many-to-one relational fields, such as country_id, 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 from the previous two steps can be obtained with the following instruction: >>> api.execute_kw(db, uid, pwd, 'res.partner', 'search_read', [domain], {'fields': ['id', 'name', 'country_id']}) The search_read method behaves like read, but expects a domain as a first positional argument instead of a list of IDs. It's worth mentioning that the fields argument on read and search_read isn't mandatory. If not provided, all fields will be retrieved. This may cause expensive computations of function fields and a large amount of data to be retrieved but probably never used, so it is generally recommended to provide an explicit list of fields. Search and read API methods We have seen, in Chapter 7, Recordsets – Working with Model Data, the most important model methods used to generate recordsets and how to write to them. But there are a few more model methods available for more specific actions, as shown here: read([fields]) is similar to the browse method, but, instead of a recordset, it returns a list of rows of data with the fields given as its argument. Each row is a dictionary. It provides a serialized representation of the data that can be sent through RPC protocols and is intended to be used by client programs and not in server logic. search_read([domain], [fields], offset=0, limit=None, order=None) performs a search operation followed by a read on the resulting record list. It's intended to be used by RPC clients and saves them the extra round trip needed when doing search followed by read on the results. All other model methods are exposed through RPC, except for the ones prefixed with an underscore, which are considered private. This means that we can use create, write, and unlink to modify data on the server as follows: >>> x = api.execute_kw(db, uid, pwd, 'res.partner', 'create', [{'name': 'Packt Pub'}]) >>> print(x) 51 >>> api.execute_kw(db, uid, pwd, 'res.partner', 'write', [[x], {'name': 'Packt Publishing'}])True >>> api.execute_kw(db, uid, pwd, 'res.partner', 'read', [[x], ['id', 'name']])[{'id': 51, 'name': 'Packt Publishing'}] >>> api.execute_kw(db, uid, pwd, 'res.partner', 'unlink', [[x]])True>>> api.execute_kw(db, uid, pwd, 'res.partner', 'read', [[x]])[] One limitation of the XML-RPC protocol is that it does not support None values. There's an XML- RPC extension that supports None values, but whether this is available will depend on the particular XML-RPC library being used on your client. Methods that don't return anything may not 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. Another alternative is to use JSON-RPC instead, also supported. The OdooRPC library allows for this, and we will use it later in this chapter, in the Using the OdooRPC library section. It is worth repeating that the Odoo external API can be used by most programming languages.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages15 Page
-
File Size-