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:

Writing a Notes desktop application

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:

import xmlrpclib
class NoteAPI():
    def __init__(self, srv, db, user, pwd):
        common = xmlrpclib.ServerProxy(
            '%s/xmlrpc/2/common' % srv)
        self.api = xmlrpclib.ServerProxy(
            '%s/xmlrpc/2/object' % srv)
        self.uid = common.authenticate(db, user, pwd, {})
        self.pwd = pwd
        self.db = db
        self.model = 'todo.task'

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:

    def execute(self, method, arg_list, kwarg_dict=None):
        return self.api.execute_kw(
            self.db, self.uid, self.pwd, self.model,
            method, arg_list, kwarg_dict or {})

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:

    def get(self, ids=None):
        domain = [('id',' in', ids)] if ids else []
        fields = ['id', 'name']
        return self.execute('search_read', [domain, fields])

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:

    def set(self, text, id=None):
        if id:
            self.execute('write', [[id], {'name': text}])
        else:
            vals = {'name': text, 'user_id': self.uid}
            id = self.execute('create', [vals])
        return id

Let's end the file with a small piece of test code that will be executed if we run the Python file:

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())

If we run the Python script, we should see the content of our to-do tasks printed out. Now that we have a simple wrapper around our Odoo backend, let's deal with the desktop user interface.

Creating the GUI

Our goal here was to learn to write the interface between an external application and the Odoo server, and this was done in the previous section. But it would be a shame not going the extra step and actually making it available to the end user.

To keep the setup as simple as possible, we will use Tkinter to implement the graphical user interface. Since it is part of the standard library, it does not require any additional installation. It is not our goal to explain how Tkinter works, so we will be short on explanations about it.

Each Task should have a small yellow window on the desktop. These windows will have a single Text widget. Pressing Ctrl + N will open a new Note, and pressing Ctrl + S will write the content of the current note to the Odoo server.

Now, alongside the note_api.py file, create a new note_gui.py file. It will first import the Tkinter modules and widgets we will use, and then the NoteAPI class, as shown in the following:

from Tkinter import Text, Tk
import tkMessageBox
from note_api import NoteAPI

Next we create our own Text widget derived from the Tkinter one. When creating an instance, it will expect an API reference, to use for the save action, and also the Task's text and ID, as shown in the following:

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('<Control-n>', self.create)
        self.bind('<Control-s>', 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)

The Tk() constructor creates a new UI window and the Text widget places itself inside it, so that creating a new NoteText instance automatically opens a desktop window.

Next, we will implement the create and save actions. The create action opens a new empty window, but it will be stored in the server only when a save action is performed, as shown in the following code:

    def create(self, event=None):
        NoteText(self.api, '')
    def save(self, event=None):
        text = self.get('1.0', 'end')
        self.id = self.api.set(text, self.id)
        tkMessageBox.showinfo('Info', 'Note %d Saved.' % self.id)

The save action can be performed either on existing or on new tasks, but there is no need to worry about that here since those cases are already handled by the set() method of NoteAPI.

Finally, we will add the code that retrieves and creates all note windows when the program is started, as shown in the following code:

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()

The last command runs mainloop() on the last Note window created, to start waiting for window events.

This is a very basic application, but the point here is to make an example of interesting ways to leverage the Odoo RPC API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset